I do not understand why phpstan (at level 9+) flags the concrete factory's makeCollection method (the last class) as returning Collection.
<?php
declare (strict_types=1);
/**
* @template ElementType
*/
interface CollectionInterface
{
}
/**
* @template ElementType
*/
interface CollectionFactoryInterface
{
/**
* @return CollectionInterface<ElementType>
*/
public function makeCollection() : CollectionInterface;
}
/**
* @template ElementType
* @implements CollectionInterface<ElementType>
*/
class Collection implements CollectionInterface
{
}
/**
* @template ElementType
* @implements CollectionFactoryInterface<ElementType>
*/
class CollectionFactory implements CollectionFactoryInterface
{
/**
* @return CollectionInterface<ElementType>
*/
public function makeCollection(): CollectionInterface
{
/* phpstan flags this */
return new Collection();
}
}
What is the correct way to typehint the code so that both the factory and the return value of the creation method (makeCollection) are compatible with their respective interfaces?
I do not understand why phpstan (at level 9+) flags the concrete factory's makeCollection method (the last class) as returning Collection.
<?php
declare (strict_types=1);
/**
* @template ElementType
*/
interface CollectionInterface
{
}
/**
* @template ElementType
*/
interface CollectionFactoryInterface
{
/**
* @return CollectionInterface<ElementType>
*/
public function makeCollection() : CollectionInterface;
}
/**
* @template ElementType
* @implements CollectionInterface<ElementType>
*/
class Collection implements CollectionInterface
{
}
/**
* @template ElementType
* @implements CollectionFactoryInterface<ElementType>
*/
class CollectionFactory implements CollectionFactoryInterface
{
/**
* @return CollectionInterface<ElementType>
*/
public function makeCollection(): CollectionInterface
{
/* phpstan flags this */
return new Collection();
}
}
What is the correct way to typehint the code so that both the factory and the return value of the creation method (makeCollection) are compatible with their respective interfaces?
Share Improve this question asked Feb 15 at 23:14 Doug WilbourneDoug Wilbourne 1532 silver badges10 bronze badges1 Answer
Reset to default 0Right now PHPStan reports this error:
Method CollectionFactory::makeCollection() should return CollectionInterface but returns Collection.
Because there’s no guarantee that new Collection
is actually CollectionInterfacr<ElementType>
. It might actually contain something else.
Four thoughts about this:
- This is a level 9 error. Level 9 is already pretty strict. You can be on level 8 and still have pretty reliable type checking without these annoyances for you.
- If the constructor of Collection accepted an array of elements typehinted with
array<ElementType>
, PHPStan would not complain about this. - You can “force” the type by casting with inline PHPDoc
@var
above the return, making the error to go away. - Once this suggestion is implemented, PHPStan will understand the code better and the error will go away: https://github/phpstan/phpstan/issues/6732#issuecomment-1062029088