Hamlet Framework / Type

1.0.0 2022-04-13 08:45 UTC

README

CI Status Packagist Packagist Coverage Status Psalm coverage

There are few aspects of specifying type of expression in PHP:

  1. The most exact specification of the type (we assume it's in psalm syntax): array<int,DateTime|null>
  2. The sequence of run time assertions: assert($records instanceof array<int,DateTime|null>)
  3. The type hint for static analysers (which is psalm at the moment): (array<int,DateTime|null>) $records
  4. The ability to derive types without string manipulation: array<int,DateTime|null> || null
  5. The ability to cast when it's safe, i.e. falsey should cast to false, etc.

This library provides the basic building blocks for type specifications. For example, the following expression:

$type = _map(
  _int(), 
  _union(
    _class(DateTime::class), 
    _null()
  )
)

creates an object of type Type<array<int,DateTime|null>>.

Asserting at run time, that the type of $records is array<int,DateTime|null>>:

$type->assert($records);

Cast $records to array<int,DateTime|null>> and throw an exception when $records cannot be cast to array<int,DateTime|null>>:

return $type->cast($records);

Combine type with other types, for example, making it nullable array<int,DateTime|null>>|null:

_union($type, _null())

Object like arrays

Object like arrays require more leg work. For example the type array{id:int,name:string,valid?:bool} corresponds to this construct:

/** @var Type<array{id:int,name:string,valid?:bool}> */
$type = _object_like([
    'id'     => _int(),
    'name'   => _string(),
    'valid?' => _bool()
]);

Quite a mouthful. Also, note the required @var as psalm currently have no support for dependent types.

If you want to assert types matching your PHPDoc you can use the type parser (WiP):

/** @var Type<array{id:int}> */
$type = Type::of('array{id:int}');

assert($type->matches($record));

Background

  • Move completely to PHPStan parsed including docblock
  • Add union and intersection types
  • Support for enums
  • Support for non-empty-* types
  • Support for tuples as int array{int,string}
  • Support for iterable|self|static|class-string
  • Better support for callables
  • Add PHPStan to QA pipeline