owned this note
owned this note
Published
Linked with GitHub
| Q | A
| ------------- | ---
| Branch? | 7.1
| Bug fix? | no
| New feature? | yes
| Deprecations? | no
| Tickets |
| License | MIT
| Doc PR | TODO
This PR introduces the brand new `TypeInfo` component
## State of the art
### Scope of the current `Symfony\Component\PropertyInfo\Type` class
Nowadays, when we need to work with types within Symfony, we have to use the `Type` class of the `PropertyInfo` component.
But what if we want to represent the type of a function's return type?
We still can use that `Type` class, but it won't make much sense as the `Symfony\Component\PropertyInfo\Type` is closely related to a property (as the namespace suggests).
Plus, when we need to extract types, we must use the `PropertyTypeExtractorInterface` service:
```php
readonly class Person
{
public function __construct(
public string $firstName,
) {
}
}
// will return an array with a single Type object representing a string
$types = $this->propertyTypeExtractor->getTypes(Person::class, 'firstName');
```
Therefore, type retrieval in Symfony is limited to properties only.
### `Symfony\Component\PropertyInfo\Type`'s conceptual limitations
On top of that, there is a clear limitation of the current `Type` class where unions, intersections or
even generics can't be properly described.
The actual workaround is that the `PropertyTypeExtractorInterface` is returning an array of `Type`, which can be interpreted as a union type.
## The `TypeInfo` component
All these reasons bring us to create the `TypeInfo` component.
The aim here is to address these issues and:
- Have a powerful `Type` definition that can handle union, intersections, and generics (and could be even more extended)
- Being able to get types from anything, such as properties, method arguments, return types, and raw strings (and can also be extended).
### `Type` classes
To ensure a powerful `Type` definition, we defined multiple classes:

The base `Type` class is an abstract one, so you'll always need to use one of the classes that inherit it.
Other types of classes are kinda self-explanatory.
### Type resolving
In the `TypeInfo` component, we added a `TypeResolverInterface`, and several implementations which allow developers to get a `Type` from many things:
- `ReflectionParameterTypeResolver` to resolve a function/method parameter type thanks to reflection
- `ReflectionPropertyTypeResolver` to resolve a property type thanks to reflection
- `ReflectionReturnTypeResolver` to resolve a function/method return type thanks to reflection
- `ReflectionTypeResolver` to resolve a `ReflectionNamedType`
- `StringTypeResolver` to resolve a type string representation. This can greatly work in combination with PHP documentation.
> That resolver will only be available if the `phpstan/phpdoc-parser` package is installed.
- `ChainTypeResolver` to iterate over resolvers and to return a type as soon as a nested resolver succeeds in resolving.
### Type Creation
We also improved a lot the DX for the type creation with factories:
```php
<?php
use Symfony\Component\TypeInfo\Type;
Type::int();
Type::nullable(Type::string());
Type::generic(Type::object(Collection::class), Type::int());
Type::list(Type::bool());
Type::intersection(Type::object(\Stringable::class), Type::object(\Iterator::class));
// Many others are available and can be
// found in Symfony\Component\TypeInfo\TypeFactoryTrait
```
### Upgrade path
This PR only introduces the `TypeInfo` component, but another one (which is already ready) will deprecate the `Symfony\Component\PropertyInfo\Type` in favor of `Symfony\Component\TypeInfo\Type`.