How to typehint this Generator?

28 Views Asked by At

My data provider is sending arrays. The first element is always a string, the second one an array of Token.

public static function dataProvider(): Generator
{
    yield ['15', [new Token(15, Lexer::T_INTEGER, 0)];
    //And so on...
}

I would like to "typehint" this provider. As suggested in this answer, I tried:

    /** 
     * @return Generator<array{string, Token<int, int|string>[]}>
     */

But PhpStan is returning an error:

  Generator expects value type 
     array{string, array<Doctrine\Common\Lexer\Token<int, int|string>>}, 
     array{'15',   array{Doctrine\Common\Lexer\Token<int, int>}       } given.
      Offset 1 (array<Doctrine\Common\Lexer\Token<int, int|string>>)
        does not accept type array{Doctrine\Common\Lexer\Token<int, int>}:
        Template type V on class Doctrine\Common\Lexer\Token is not
        covariant. Learn more:
        https://phpstan.org/blog/whats-up-with-template-covariant

I read the mentioned link and this one "Type-safe iterators and generators", but I still don't understand how to type-safe this Generator correctly.

I know that the error disappear when I use @return Generator<array{string, Token[]}>, but I need to specify types in Token. FI, the errors are replaced by

Method LongitudeOne\Geo\String\Tests\LexerTest::dataProvider() return type with generic class Doctrine\Common\Lexer\Token does not specify its types: T, V

If it could help, class Token is declared in doctrine/lexer:

/**
 * @template T of UnitEnum|string|int
 * @template V of string|int
 * @implements ArrayAccess<string,mixed>
 */
final class Token implements ArrayAccess
0

There are 0 best solutions below