Skip to content

Working with types

TypeReflector represents a single resolved PHP type and answers questions about it: what kind of type it is, whether it accepts a given value, and how it relates to other types. It understands builtins, classes, interfaces, enums, unions and intersections.

Creating a type reflector

The constructor normalizes several inputs into a single type definition: a native ReflectionType, a ReflectionParameter, a ReflectionProperty, a ReflectionClass, any other Reflector, or a plain type string.

php
<?php
declare(strict_types=1);

use Raxos\Reflection\TypeReflector;

$type = new TypeReflector('int|string');
$type = new TypeReflector(User::class);

In practice you usually get one from another reflector, for example a property or parameter type.

php
use function Raxos\Reflection\reflect;

$type = reflect(User::class)->getProperty('id')->getType();

echo $type->getName();      // int
echo $type->getShortName(); // int

Validating values

accepts() checks whether a runtime value matches the type. It handles builtins through their native is_* checks, class types through instanceof, iterables, and both union and intersection members.

php
$type = new TypeReflector('int|string');

$type->accepts(42);    // true
$type->accepts('foo'); // true
$type->accepts(3.14);  // false

Nullable types accept null in addition to their declared type.

php
$type = new TypeReflector('?User');

$type->accepts(null); // true

Classifying a type

A group of predicates describe what kind of type it is.

php
$type = new TypeReflector(Status::class);

$type->isBuiltIn();    // false
$type->isClass();      // false, an enum is not a plain class
$type->isEnum();       // true
$type->isBackedEnum(); // true when Status is a backed enum
$type->isUnitEnum();   // true for any enum
$type->isIterable();   // false

Other predicates include isScalar(), isInterface(), isStringable() and isNullable(). isIterable() returns true for array, iterable, Generator and any Iterator.

Comparing types

matches() checks whether the type is the same as, or a subtype of, a given class or interface name. equals() compares two type definitions for exact equality.

php
$type = new TypeReflector(User::class);

$type->matches(JsonSerializable::class);       // true when User implements it
$type->equals('Full\Qualified\User');          // true
$type->equals(new TypeReflector(User::class)); // true

When the type names a class, class() returns a ClassReflector so you can keep navigating.

php
$reflector = $type->class(); // ClassReflector

Splitting unions and intersections

split() breaks a union or intersection type into its individual TypeReflector parts, which is handy when you want to validate against each member.

php
$type = new TypeReflector('int|string|null');

foreach ($type->split() as $part) {
    echo $part->getName() . "\n"; // int, string, null
}