如何在PHP中为生成器(generators)添加类型提示?

7

假设你有这样一个类:

class MyClass
{
    public function __construct(public int $id, public string $foo)
    {
    }
}

还有一个生成器,可以像这样创建该类的多个实例:

$myGenerator = function (): \Generator {
     yield new MyClass(id: 21, foo: 'fnord');
     yield new MyClass(id: 13, foo: 'baz');
     yield new MyClass(id: 42, foo: 'Thanks for the fish');
};

我该如何为生成器函数添加类型提示,以便在迭代期间推断每个元素的类型?
foreach ($myGenerator as $instance) {
    $instance-> // no autocompletion in IDE as type is not known
}

我不想做的事情:

foreach ($myGenerator as $instance) {
    /** @var MyClass $instance */
    $instance-> // now autocomplete works inside an IDE
}

由于每次使用生成器时都需要冗余的类型提示,因此我希望在生成器的返回类型层面提供一次类型提示。

有没有更好的替代方法来对生成器进行类型提示?

在伪代码中,我希望能够按照以下方式进行操作:

$myGenerator = function (): \Generator<MyClass> {...}

我认为 PHP 的类型系统不能胜任这项任务,我不介意使用 PHPDoc / PHPStan。主要用途是 IDE 支持(在我的情况下是 PhpStorm,但应该适用于其他 IDE)。


1
显然,通过phpstan可能是可行的,但我还不知道如何在phpstorm中激活:https://phpstan.org/blog/generics-in-php-using-phpdocs - k0pernikus
PhpStorm最新版本已经添加了对泛型的支持,该版本在几天前发布 - 因此,如果您可以使用PHPDocs进行此操作(这并不意味着您必须使用PHPStan,因为PhpStorm和PHPStan仅读取该数据),那么在更新PhpStorm后可能会有所帮助。 - Nico Haase
@NicoHaase,您所说的最新版本是指2021.2还是EAP?因为在我的机器上,2021.2似乎无法正常运行。您能否详细说明一下? - k0pernikus
@NicoHaase 我找到了这篇博客文章,虽然它讨论了泛型文档,但我不知道它是否适用于生成器以及如何使用。https://blog.jetbrains.com/phpstorm/2021/07/phpstorm-2021-2-beta/ - k0pernikus
是的,就像那样?还是像 /** @var MyClass[] $generator **/ 这样? - Nico Haase
1个回答

8

像phpdoc中的其他集合一样

/**
* @return \Generator|MyClass[]
*/
$myGenerator = function (): \Generator {
   yield new MyClass(id: 21, foo: 'fnord');
   yield new MyClass(id: 13, foo: 'baz');
   yield new MyClass(id: 42, foo: 'Thanks for the fish');
};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接