Skip to content

Commit

Permalink
minor symfony#20407 [TypeInfo] Add more details to TypeInfo documenta…
Browse files Browse the repository at this point in the history
…tion (Korbeil)

This PR was merged into the 7.2 branch.

Discussion
----------

[TypeInfo] Add more details to TypeInfo documentation

This pull request is to revamp current TypeInfo documentation.
I tried to make the most of the recent changes while answering `@javiereguiluz`'s issue (thanks to "PHPDoc parsing" part).

It should fixes symfony#20389, symfony#20064 and symfony#20014.

Commits
-------

dc999f3 Add more details to TypeInfo documentation
  • Loading branch information
javiereguiluz committed Dec 10, 2024
2 parents c51ca3b + dc999f3 commit 5cf517d
Showing 1 changed file with 97 additions and 3 deletions.
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

0 comments on commit 5cf517d

Please sign in to comment.