From c442732fb48d1da7f781e38982ec53975a39e915 Mon Sep 17 00:00:00 2001 From: Toon Verwerft Date: Fri, 5 Apr 2024 15:40:18 +0200 Subject: [PATCH] docs(type) Provides an initial documentation document for the Type component --- docs/README.md | 2 +- docs/component/type.md | 72 --- docs/documenter.php | 1 - docs/templates/README.template.md | 1 + src/Psl/Type/README.md | 923 ++++++++++++++++++++++++++++++ 5 files changed, 925 insertions(+), 74 deletions(-) delete mode 100644 docs/component/type.md create mode 100644 src/Psl/Type/README.md diff --git a/docs/README.md b/docs/README.md index 2dc967f7..4e025bdd 100644 --- a/docs/README.md +++ b/docs/README.md @@ -9,6 +9,7 @@ * [Psl\Async](../src/Psl/Async/README.md) * [Psl\Default](../src/Psl/Default/README.md) * [Psl\Range](../src/Psl/Range/README.md) + * [Psl\Type](../src/Psl/Type/README.md) --- @@ -53,7 +54,6 @@ - [Psl\Str\Grapheme](./component/str-grapheme.md) - [Psl\TCP](./component/tcp.md) - [Psl\Trait](./component/trait.md) -- [Psl\Type](./component/type.md) - [Psl\Unix](./component/unix.md) - [Psl\Vec](./component/vec.md) diff --git a/docs/component/type.md b/docs/component/type.md deleted file mode 100644 index 7656de12..00000000 --- a/docs/component/type.md +++ /dev/null @@ -1,72 +0,0 @@ - - -[*index](./../README.md) - ---- - -### `Psl\Type` Component - -#### `Functions` - -- [array_key](./../../src/Psl/Type/array_key.php#L14) -- [backed_enum](./../../src/Psl/Type/backed_enum.php#L18) -- [bool](./../../src/Psl/Type/bool.php#L14) -- [class_string](./../../src/Psl/Type/class_string.php#L16) -- [converted](./../../src/Psl/Type/converted.php#L23) -- [dict](./../../src/Psl/Type/dict.php#L18) -- [f32](./../../src/Psl/Type/f32.php#L16) -- [f64](./../../src/Psl/Type/f64.php#L16) -- [float](./../../src/Psl/Type/float.php#L14) -- [i16](./../../src/Psl/Type/i16.php#L16) -- [i32](./../../src/Psl/Type/i32.php#L16) -- [i64](./../../src/Psl/Type/i64.php#L16) -- [i8](./../../src/Psl/Type/i8.php#L16) -- [instance_of](./../../src/Psl/Type/instance_of.php#L16) -- [int](./../../src/Psl/Type/int.php#L14) -- [intersection](./../../src/Psl/Type/intersection.php#L20) -- [is_nan](./../../src/Psl/Type/is_nan.php#L14) -- [iterable](./../../src/Psl/Type/iterable.php#L18) -- [literal_scalar](./../../src/Psl/Type/literal_scalar.php#L16) -- [map](./../../src/Psl/Type/map.php#L20) -- [mixed](./../../src/Psl/Type/mixed.php#L14) -- [mixed_dict](./../../src/Psl/Type/mixed_dict.php#L12) -- [mixed_vec](./../../src/Psl/Type/mixed_vec.php#L12) -- [mutable_map](./../../src/Psl/Type/mutable_map.php#L20) -- [mutable_vector](./../../src/Psl/Type/mutable_vector.php#L18) -- [non_empty_dict](./../../src/Psl/Type/non_empty_dict.php#L18) -- [non_empty_string](./../../src/Psl/Type/non_empty_string.php#L14) -- [non_empty_vec](./../../src/Psl/Type/non_empty_vec.php#L16) -- [nonnull](./../../src/Psl/Type/nonnull.php#L16) -- [null](./../../src/Psl/Type/null.php#L14) -- [nullable](./../../src/Psl/Type/nullable.php#L16) -- [num](./../../src/Psl/Type/num.php#L14) -- [numeric_string](./../../src/Psl/Type/numeric_string.php#L14) -- [object](./../../src/Psl/Type/object.php#L14) -- [optional](./../../src/Psl/Type/optional.php#L16) -- [positive_int](./../../src/Psl/Type/positive_int.php#L16) -- [resource](./../../src/Psl/Type/resource.php#L14) -- [scalar](./../../src/Psl/Type/scalar.php#L14) -- [shape](./../../src/Psl/Type/shape.php#L17) -- [string](./../../src/Psl/Type/string.php#L14) -- [u16](./../../src/Psl/Type/u16.php#L16) -- [u32](./../../src/Psl/Type/u32.php#L16) -- [u8](./../../src/Psl/Type/u8.php#L16) -- [uint](./../../src/Psl/Type/uint.php#L16) -- [union](./../../src/Psl/Type/union.php#L18) -- [unit_enum](./../../src/Psl/Type/unit_enum.php#L18) -- [vec](./../../src/Psl/Type/vec.php#L16) -- [vector](./../../src/Psl/Type/vector.php#L18) - -#### `Interfaces` - -- [TypeInterface](./../../src/Psl/Type/TypeInterface.php#L13) - -#### `Classes` - -- [Type](./../../src/Psl/Type/Type.php#L14) - - diff --git a/docs/documenter.php b/docs/documenter.php index 1fd92dd4..54931a03 100644 --- a/docs/documenter.php +++ b/docs/documenter.php @@ -223,7 +223,6 @@ function get_all_components(): array 'Psl\\Str\\Grapheme', 'Psl\\TCP', 'Psl\\Trait', - 'Psl\\Type', 'Psl\\Unix', 'Psl\\Locale', 'Psl\\Vec', diff --git a/docs/templates/README.template.md b/docs/templates/README.template.md index 278bb739..13224712 100644 --- a/docs/templates/README.template.md +++ b/docs/templates/README.template.md @@ -9,6 +9,7 @@ * [Psl\Async](../src/Psl/Async/README.md) * [Psl\Default](../src/Psl/Default/README.md) * [Psl\Range](../src/Psl/Range/README.md) + * [Psl\Type](../src/Psl/Type/README.md) --- diff --git a/src/Psl/Type/README.md b/src/Psl/Type/README.md new file mode 100644 index 00000000..4358c8b0 --- /dev/null +++ b/src/Psl/Type/README.md @@ -0,0 +1,923 @@ +# Type + +## Introduction + +The type component provides a set functions to ensure that a given value is of a specific type **at Runtime**. +It aims to provide a solution for the [Parse, Don't Validate](https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/) problem. + +## Usage + +```php +use Psl; +use Psl\Type; + +$untrustedInput = $request->get('input'); + +// Turns a string-like value into a non-empty-string +$trustedInput = Type\non_empty_string()->coerce($untrustedInput); + +// Or assert that its already a non-empty-string +$trustedInput = Type\non_empty_string()->assert($untrustedInput); + +// Or check if its a non-empty-string +$isTrustworthy = Type\non_empty_string()->matches($untrustedInput); +``` + +Every type provided by this component is an instance of `Type\TypeInterface`. +This interface provides the following methods: + +- `matches(mixed $value): $value is Tv` - Checks if the provided value is of the type. +- `assert(mixed $value): Tv` - Asserts that the provided value is of the type or throws an `AssertException` on failure. +- `coerce(mixed $value): Tv` - Coerces the provided value into the type or throws a `CoercionException` on failure. + + +## Static Analysis + +Your static analyzer fully understands the types provided by this component. +But it takes an additional step to activate this knowledge: + +### Psalm Integration + +Please refer to the [`php-standard-library/psalm-plugin`](https://github.com/php-standard-library/psalm-plugin) repository. + +### PHPStan Integration + +Please refer to the [`php-standard-library/phpstan-extension`](https://github.com/php-standard-library/phpstan-extension) repository. + +## API + +### Functions + +#### [array_key](array_key.php) + +```hack +@pure +Type\array_key(): TypeInterface +``` + +Provides a type that can parse array-keys. + +Can coerce from: + +* `string`: The [string()](#string) type is used to coerce the input value to a string. +* `int`: The [`int()`](#int) type is used to coerce the input value to an integer. + +--- + +#### [backed_enum](backed_enum.php) + +```hack +@pure +@template T of BackedEnum +Type\backed_enum(class-string $enum): TypeInterface +``` + +Provides a type that can parse backed-enums. + +Can coerce from: + +* `string` when `T` is a string-backed enum. +* `int` when `T` is a string-backed enum. + +--- + +#### [bool](bool.php) + +```hack +@pure +Type\bool(): TypeInterface +``` + +Can coerce from: + +* `bool`: `true` or `false` +* `int`: `1` or `0` +* `string`: `'1'` or `'0'` + +--- + +#### [class_string](class_string.php) + +```hack +@pure +@template T of object +Type\class_string(class-string $classname): TypeInterface> +``` + +Provides a type that can parse class-strings. + +Can coerce from: + +* `string` when `T` is a string that indicates the Fully-Qualified class-name of `T` or one of its subclasses. + +Examples: + +```php +use Psl\Type; + +Type\class_string(stdClass::class)->assert(stdClass::class); +Type\class_string(SomeInterface::class)->assert(SomeInterface::class); +Type\class_string(SomeInterface::class)->assert(SomeImplementation::class); +``` + +--- + +#### [converted](class_string.php) + +```hack +@pure +@template I of mixed +@template O of mixed +Type\converted(TypeInterface $from, TypeInteface $into, (Closure(I): O) $converter): TypeInterface +``` + +Provides a type `O` that can be converted from a type `I` using a converter function. + +* During `assert()`, this type will assert that the value matches the `$into of O` type. No conversion will be applied. +* During `coerce()` this type will convert the input value through a couple of different stages: + * When the original input is already of the output type, it is returned as is. + * `coerce_input(mixed): I` The mixed input value will be coerced to the `$from of I` type. + * `covert(I): mixed` The input of type `I` will be converted using the `$converter` function. + * `coerce_output(mixed): O` The output of the converter function will be coerced to the `$into of O` type. + +These are some examples on how the type can be used: + +```php +use Psl\Type; + +$dateTimeType = Type\converted( + Type\string(), + Type\instance_of(DateTimeImmutable::class), + static function (string $value): DateTimeImmutable { + $date = DateTimeImmutable::createFromFormat('Y-m-d H:i:s', $value); + if (!$date) { + // Exceptions will be transformed to CoerceException + throw new \RuntimeException('Invalid format given. Expected date to be of format {format}'); + } + + return $date; + } +); + +$emailType = Type\converted( + Type\string(), + Type\instance_of(EmailValueObject::class), + static function (string $value): EmailValueObject { + // Exceptions will be transformed to CoerceException + return EmailValueObject::tryParse($value); + } +); + +$shape = Type\shape([ + 'email' => $emailType, + 'dateTime' => $dateTimeType +]); + +// Coerce will convert from -> into, If the provided value is already into - it will skip conversion. +$coerced = $shape->coerce($data); + +// Assert will check if the value is of the type it converts into! +$shape->assert($coerced); +``` + +This type can also be used to transform array-shaped values into custom Data-Transfer-Objects: + +```php +use Psl\Type; +use Psl\Type\TypeInterface; + +/** +* @psalm-immutable +*/ +final class Person { + public function __construct( + public readonly string $firstName, + public readonly string $lastName, + ) { + } + + /** + * @pure + * + * @return TypeInterface + */ + public static function type(): TypeInterface { + return Type\converted( + Type\shape([ + 'firstName' => Type\string(), + 'lastName' => Type\string(), + ]), + Type\instance_of(Person::class), + fn (array $data): Person => new Person( + $data['firstName'], + $data['lastName'] + ) + ); + } + + /** + * @pure + */ + public static function parse(mixed $data): self + { + return self::type()->coerce($data); + } +} + +// The Person::type() function can now be used as its own type so that it can easily be reused throughout your application. + +$nested = Type\shape([ + 'person' => Person::type(), +]); +``` + +When the converter coercion fails, you will get detailed information about what went wrong in which specific conversion stage: + +> Could not coerce "int" to type "class-string" **at path "coerce_input(int): class-string**" + +> Could not coerce "int" to type "string" **at path "convert(string): string": Internal converter error**. + +> Could not coerce "string" to type "class-string" **at path "coerce_output(string): class-string**". + +--- + +#### [dict](dict.php) + +```hack +@pure +@template Tk of array-key +@template Tv of mixed +Type\dict(TypeInterface $key_type, TypeInterface $value_type): TypeInterface> +``` + +Provides a type that can parse array dictionaries. The `Tv` type can consist out of advanced types like shapes, vectors, or other dictionaries. + +Can coerce from: + +* `iterable`: The iterable will be iterated: + * Every item's key will be coerced by the provided `Tk` type. + * Every item's value will be coerced by the provided `Tv` type. + +These are some examples on how the type can be used: + +```php +use Psl\Type; + +$dict = Type\dict( + Type\string(), + Type\shape([ + 'title' => Type\string(), + 'content' => Type\string(), + ]) +); + +$dict->assert([ + 'string-key' => [ + 'title' => 'Hello world', + 'content' => 'A book that greets the world in all possible languages!', + ] +]); +``` + +When the iterable does not match the specified dictionary, you will get detailed information about what went wrong exactly: + +> Expected "dict", got "int" **at path "key(123)"**. + +> Expected "dict", got "int" **at path "foo.title"**. + +--- + +#### [f32](f32.php) + +```hack +@pure +Type\f32(): TypeInterface +``` + +Provides a type that can parse floats with a range `float<-3.40282347E+38, 3.40282347E+38>`. + +Can coerce from: + +* This type will use the same coercion rules as the [`float()`](#float) type whilst guarding the float range. + +--- + +#### [f64](f64.php) + +```hack +@pure +Type\f64(): TypeInterface +``` + +Provides a type that can parse floats with a range `float<-1.7976931348623157E+308, 1.7976931348623157E+308>`. + +Can coerce from: + +* This type will use the same coercion rules as the [`float()`](#float) type whilst guarding the float range. + +--- + +#### [float](float.php) + +```hack +@pure +Type\float(): TypeInterface +``` + +Provides a type that can parse floats. + +Can coerce from: + +* `float`: Will convert the float AS-IS. +* `int`: Will convert the integer into a float. +* `string`: Will convert the string to a float if it is a numeric string or if it matches a float pattern. +* `\Stringable`: Will call `__toString()` on the object and apply the same logic as on regular strings. + +--- + +#### [i8](i8.php) + +```hack +@pure +Type\i8(): TypeInterface> +``` + +Provides a type that can parse integers with a range `int<-128, 127>`. + +Can coerce from: + +* This type will use the same coercion rules as the [`int()`](#int) type whilst guarding the integer range. + +--- + +#### [i16](i16.php) + +```hack +@pure +Type\i16(): TypeInterface +``` + +Provides a type that can parse integers with a range `int<-32768, 32767>`. + +Can coerce from: + +* This type will use the same coercion rules as the [`int()`](#int) type whilst guarding the integer range. + +--- + +#### [i32](i32.php) + +```hack +@pure +Type\i32(): TypeInterface +``` + +Provides a type that can parse integers with a range `int<-2147483648, 2147483647>`. + +Can coerce from: + +* This type will use the same coercion rules as the [`int()`](#int) type whilst guarding the integer range. + +--- + +#### [i64](i64.php) + +```hack +@pure +Type\i64(): TypeInterface +``` + +Provides a type that can parse integers with a range `int`. + +Can coerce from: + +* This type will use the same coercion rules as the [`int()`](#int) type whilst guarding the integer range. + +--- + +#### [instance_of](instance_of.php) + +```hack +@pure +@template T of object +Type\instance_of(class-string $classname): TypeInterface +``` + +Provides a type that can parse objects of a specific class. + +Can coerce from: + +* `object` : Only objects and class instances are accepted and are validated against the provided (base) class-name. + +Examples: + +```php +use Psl\Type; + +Type\instance_of(stdClass::class)->assert(stdClass::class); +Type\instance_of(SomeInterface::class)->assert($someImplementation); +``` + +--- + +#### [int](int.php) + +```hack +@pure +Type\int(): TypeInterface +``` + +Provides a type that can parse integers. + +Can coerce from: + +* `int`: Will convert the integer AS-IS. +* `float`: Will return the whole part of the float if the decimal part is `.00` +* `string`: Will convert the string to an integer if it is a valid integer string. +* `\Stringable`: Will call `__toString()` on the object and apply the same logic as on regular strings. + +--- + +#### [intersection](intersection.php) +--- +#### [is_nan](is_nan.php) +--- +#### [iterable](iterable.php) +--- +#### [literal_scalar](literal_scalar.php) +--- +#### [map](map.php) +--- +#### [mixed](mixed.php) +```hack +@pure +Type\mixed(): TypeInterface +``` + +Provides a type that can parse `mixed`. (so basically anything) + +Can coerce from: + +* anything : mixed is the most permissive type, so it will accept any input value. + +#### [mixed_dict](mixed_dict.php) + +```hack +@pure +Type\mixed_dict(): TypeInterface> +``` + +Provides a type that can parse any array dictionaries. + +Can coerce from: + +* `iterable`: It will make sure the array-key is a string or an integer allowing it to have any value. + +--- + +#### [mixed_vec](mixed_vec.php) + +```hack +@pure +Type\mixed_vec(): TypeInterface> +``` + +Provides a type that can parse any array list. + +Can coerce from: + +* `iterable`: It will make sure the provided value is an iterable and will coerce every item to mixed. + +--- + +#### [mutable_map](mutable_map.php) +--- +#### [mutable_vector](mutable_vector.php) +--- +#### [non_empty_dict](non_empty_dict.php) + +```hack +@pure +@template Tk of array-key +@template Tv of mixed +Type\non_empty_dict(TypeInterface $key_type, TypeInterface $value_type): TypeInterface> +``` + +Provides a type that can parse non-empty array dictionaries. + +Can coerce from: + +* `iterable`: It uses the same coercion rules as the [`dict()`](#dict) type whilst guarding the non-empty array. + +--- + +#### [non_empty_string](non_empty_string.php) + +```hack +@pure +Type\non_empty_string(): TypeInterface +``` + +Provides a type that can parse a non-empty-string. + +Can coerce from: + +* This type will use the same coercion rules as the [`string()`](#string) type whilst guarding the non-empty string. + +--- + +#### [non_empty_vec](non_empty_vec.php) + +```hack +@pure +@template Tv of mixed +Type\non_empty_vec(TypeInterface $value_type): TypeInterface> +``` + +Provides a type that can parse non-empty array lists. + +Can coerce from: + +* `iterable`: It uses the same coercion rules as the [`vec()`](#vec) type whilst guarding the non-empty array. + +--- + +#### [nonnull](nonnull.php) +```hack +@pure +Type\nonnull(): TypeInterface +``` + +Provides a type that can parse `non-null`. Non-null is considered to be equal to `mixed` without `null. + +Can coerce from: + +* `non-null` : This type accepts any input you give it, except `null`. + +Both `assert()` and `coerce()` are designed to narrow down the provided type: + +```php +use Psl\Type; + +$nullable = Type\nonnull(); +$nullable->assert($stringOrNull); + +// Your static analyzer will know that $stringOrNull is a string ! + +``` + +--- + +#### [null](null.php) +```hack +@pure +Type\null(): TypeInterface +``` + +Provides a type that can parse `null`. (so basically anything) + +Can coerce from: + +* `null` : Only `null` is accepted as a valid input value. + +--- + +#### [nullable](nullable.php) +```hack +@pure +@template Tv of mixed +Type\nullable(TypeInterface $inner_type): TypeInterface +``` + +Provides a type that can parse `null | Tv`. + +Can coerce from: + +* `null` : The provided `null` value will be returned as is. +* `mixed` : The provided value will be coerced by the provided `Tv` type. + +```php +use Psl\Type; + +$nullableString = Type\nonnull(Type\string()); +$nullable->assert($stringOrNull); +``` + +--- + +#### [num](num.php) + +```hack +@pure +Type\num(): TypeInterface +``` + +Provides a type that can parse numeric values. + +Can coerce from: + +* `int`: The [`int()`](#int) type is used to coerce the input value to an integer. +* `float`: The [`float()`](#float) type is used to coerce the input value to a float. + +--- + +#### [numeric_string](numeric_string.php) + +```hack +@pure +Type\numeric_string(): TypeInterface +``` + +Provides a type that can parse a numeric-string. + +Can coerce from: + +* `string`: The provided string will be checked if it is a numeric string. +* `num`: The provided numeric value will be converted to a string. +* `\Stringable`: The provided value will be coerced to a string and checked if it is a numeric string. + +--- + +#### [object](object.php) +```hack +@pure +Type\object(): TypeInterface +``` + +Provides a type that can parse `mixed`. (so basically anything) + +Can coerce from: + +* `object` : Only objects and class instances are accepted as a valid input value. + +--- + +#### [optional](optional.php) +```hack +@pure +@template Tv of mixed +Type\optional(TypeInterface $inner_type): TypeInterface +``` + +Provides a type that can parse `?Tv`. + +Can coerce from: + +* `undefined` : The type will be ignored when being validated inside a shape. +* `mixed` : The provided value will be coerced by the provided `Tv` type. + +```php +use Psl\Type; + +$nullableString = Type\nonnull(Type\string()); +$nullable->assert($stringOrNull); +``` + +--- + +#### [positive_int](positive_int.php) + +```hack +@pure +Type\positive_int(): TypeInterface +``` + +Provides a type that can parse integers with a range `int<1, max>`. + +Can coerce from: + +* This type will use the same coercion rules as the [`int()`](#int) type whilst guarding the integer range. + +--- + +#### [resource](resource.php) + +```hack +@pure +@template Tkind of string +Type\resource(?Tkind $kind): TypeInterface> +``` + +Provides a type that can parse `resource`. +When a kind is specified, the resource will be checked if it is of that kind by using the [get_resource_type](https://www.php.net/manual/en/function.get-resource-type.php) method. + +Can coerce from: + +* `resource` : Only resources are accepted as a valid input value. + +Examples: + +```php +use Psl\Type; + +$resource = Type\resource()->assert($resource); +$curlResource = Type\resource('curl')->assert($resource); +$streamResource = Type\resource('stream')->assert($resource); +``` + +--- + +#### [scalar](scalar.php) +--- +#### [shape](shape.php) + +```hack +@pure +@template Tk of array-key +@template Tv of mixed +Type\shape(dict $elements, bool $allow_unknown_fields = false): TypeInterface> +``` + +Provides a type that can parse (deeply nested) iterables. A shape can consist out of multiple child-shapes and structures. + +* During `assert()` the type will assert that every child has a valid child-type. +* During `coerce()` the type will coerce every child element into its corresponding child-type. + +```php +use Psl\Type; + +$shape = Type\shape([ + 'name' => Type\string(), + 'articles' => Type\vec(Type\shape([ + 'title' => Type\string(), + 'content' => Type\string(), + 'likes' => Type\int(), + 'comments' => Type\optional( + Type\vec(Type\shape([ + 'user' => Type\string(), + 'comment' => Type\string() + ])) + ), + ])), + 'dictionary' => Type\dict(Type\string(), Type\vec(Type\shape([ + 'title' => Type\string(), + 'content' => Type\string(), + ]))), + 'pagination' => Type\optional(Type\shape([ + 'currentPage' => Type\uint(), + 'totalPages' => Type\uint(), + 'perPage' => Type\uint(), + 'totalRows' => Type\uint(), + ])) +]); + +$validData = $shape->coerce([ + 'name' => 'ok', + 'articles' => [ + [ + 'title' => 'ok', + 'content' => 'ok', + 'likes' => 1, + 'comments' => [ + [ + 'user' => 'ok', + 'comment' => 'ok' + ], + [ + 'user' => 'ok', + 'comment' => 'ok', + ] + ] + ] + ], + 'dictionary' => [ + 'key' => [ + [ + 'title' => 'ok', + 'content' => 'ok', + ] + ] + ] +]); +``` + +When the data structure does not match the specified shape, you will get detailed information about what went wrong exactly: + +> Expected "array{'name': string, 'articles': vec}>, 'dictionary': dict>, 'pagination'?: array{'currentPage': uint, 'totalPages': uint, 'perPage': uint, 'totalRows': uint}}", got "int" **at path "articles.0.comments.0.user"**. + +--- + +#### [string](string.php) + +```hack +@pure +Type\string(): TypeInterface +``` + +Provides a type that can parse string. + +Can coerce from: + +* `string`: Will return the string AS-IS. +* `int`: Will convert the integer to a string. +* `\Stringable`: Will call `__toString()` on the object. + +If you wish to convert a `float` to a string, please use [numeric_string()](#numeric_string) instead. + +--- + +#### [u8](u8.php) + +```hack +@pure +Type\u8(): TypeInterface +``` + +Provides a type that can parse integers with a range `int<0, 255>`. + +Can coerce from: + +* This type will use the same coercion rules as the [`int()`](#int) type whilst guarding the integer range. + +--- + +#### [u16](u16.php) + +```hack +@pure +Type\u16(): TypeInterface +``` + +Provides a type that can parse integers with a range `int<0, 65535>`. + +Can coerce from: + +* This type will use the same coercion rules as the [`int()`](#int) type whilst guarding the integer range. + +--- + +#### [u32](u32.php) + +```hack +@pure +Type\u32(): TypeInterface +``` + +Provides a type that can parse integers with a range `int<0, 4294967295>`. + +Can coerce from: + +* This type will use the same coercion rules as the [`int()`](#int) type whilst guarding the integer range. + +--- + +#### [uint](uint.php) + +```hack +@pure +Type\uint(): TypeInterface +``` + +Provides a type that can parse integers with a range `int<0, max>`. + +Can coerce from: + +* This type will use the same coercion rules as the [`int()`](#int) type whilst guarding the integer range. + +--- + +#### [union](union.php) +--- +#### [unit_enum](unit_enum.php) +--- +#### [vec](vec.php) + +```hack +@pure +@template Tv of mixed +Type\vec(TypeInterface $value_type): TypeInterface> +``` + +Provides a type that can parse array lists. The `Tv` type can consist out of advanced types like shapes, vectors, or other dictionaries. + +Can coerce from: + +* `iterable`: The iterable will be iterated: + * Every item's value will be coerced by the provided `Tv` type. + +These are some examples on how the type can be used: + +```php +use Psl\Type; + +$vec = Type\vec(Type\shape([ + 'user' => Type\string(), + 'comment' => Type\string() +])); + +$vec->assert([ + ['user' => 'john', 'comment' => 'hello'], + ['user' => 'jane', 'comment' => 'world'] +]); +``` + +When the iterable value does not match the specified type, you will get detailed information about what went wrong exactly: + +> Expected "vec", got "int" **at path "0.user".** + +> Could not coerce "stdClass" to type "vec" **at path "foo.user".** + +--- + +#### [vector](vector.php) +---