admin管理员组

文章数量:1244424

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 badges
Add a comment  | 

1 Answer 1

Reset to default 0

Right 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:

  1. 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.
  2. If the constructor of Collection accepted an array of elements typehinted with array<ElementType>, PHPStan would not complain about this.
  3. You can “force” the type by casting with inline PHPDoc @var above the return, making the error to go away.
  4. 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

本文标签: phpstan generics and factory return typeStack Overflow