Skip to content

[TypeInfo] Add more details to TypeInfo documentation #20407

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 10, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 97 additions & 3 deletions components/type_info.rst
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,24 @@ to the :class:`Symfony\\Component\\TypeInfo\\Type` static methods as following::
// Many others are available and can be
// found in Symfony\Component\TypeInfo\TypeFactoryTrait

Resolvers
~~~~~~~~~

The second way of using the component is to use ``TypeInfo`` to resolve a type
based on reflection or a simple string::
based on reflection or a simple string, this is aimed towards libraries that wants to
describe a class or anything that has a type easily::

use Symfony\Component\TypeInfo\Type;
use Symfony\Component\TypeInfo\TypeResolver\TypeResolver;

class Dummy
{
public function __construct(
public int $id,
) {
}
}

// Instantiate a new resolver
$typeResolver = TypeResolver::create();

Expand All @@ -70,6 +82,88 @@ Each of these calls will return you a ``Type`` instance that corresponds to the
static method used. You can also resolve types from a string (as shown in the
``bool`` parameter of the previous example)

.. note::
PHPDoc parsing
~~~~~~~~~~~~~~

To support raw string resolving, you need to install ``phpstan/phpdoc-parser`` package.
But most times you won't have clean typed properties or you want a more precise type
thank to advanced PHPDoc, to do that you would want a string resolver based on that PHPDoc.
First you will require ``phpstan/phpdoc-parser`` package from composer to support string
revolving. Then you would do as following::

use Symfony\Component\TypeInfo\TypeResolver\TypeResolver;

class Dummy
{
public function __construct(
public int $id,
/** @var string[] $tags */
public array $tags,
) {
}
}

$typeResolver = TypeResolver::create();
$typeResolver->resolve(new \ReflectionProperty(Dummy::class, 'id')); // returns an "int" Type
$typeResolver->resolve(new \ReflectionProperty(Dummy::class, 'id')); // returns a collection with "int" as key and "string" as values Type

Advanced usages
~~~~~~~~~~~~~~~

There is many methods to manipulate and check types depending on your needs within the TypeInfo components.

If you need a check a simple Type::

// You need to check if a Type
$type = Type::int(); // with a simple int type
// You can check if a given type comply with a given identifier
$type->isIdentifiedBy(TypeIdentifier::INT); // true
$type->isIdentifiedBy(TypeIdentifier::STRING); // false

$type = Type::union(Type::string(), Type::int()); // with an union of int and string types
// You can now see that the second check will pass to true since we have an union with a string type
$type->isIdentifiedBy(TypeIdentifier::INT); // true
$type->isIdentifiedBy(TypeIdentifier::STRING); // true

class DummyParent {}
class Dummy extends DummyParent implements DummyInterface {}
$type = Type::object(Dummy::class); // with an object Type
// You can check is the Type is an object, or even if it's a given class
$type->isIdentifiedBy(TypeIdentifier::OBJECT); // true
$type->isIdentifiedBy(Dummy::class); // true
// Or inherits/implements something
$type->isIdentifiedBy(DummyParent::class); // true
$type->isIdentifiedBy(DummyInterface::class); // true

Sometimes you want to check for more than one thing at a time so a callable may be better to check everything::

class Foo
{
private int $integer;
private string $string;
private ?float $float;
}

$reflClass = new \ReflectionClass(Foo::class);

$resolver = TypeResolver::create();
$integerType = $resolver->resolve($reflClass->getProperty('integer'));
$stringType = $resolver->resolve($reflClass->getProperty('string'));
$floatType = $resolver->resolve($reflClass->getProperty('float'));

// your callable to check whatever you need
// here we want to validate a given type is a non nullable number
$isNonNullableNumber = function (Type $type): bool {
if ($type->isNullable()) {
return false;
}

if ($type->isIdentifiedBy(TypeIdentifier::INT) || $type->isIdentifiedBy(TypeIdentifier::FLOAT)) {
return true;
}

return false;
};

$integerType->isSatisfiedBy($isNonNullableNumber); // true
$stringType->isSatisfiedBy($isNonNullableNumber); // false
$floatType->isSatisfiedBy($isNonNullableNumber); // false
Loading