返回

数组值生成器类型提示:使用泛型和约束提高代码安全性

php

如何对数组值中的生成器进行类型提示?

问题概述

在 PHP 中,生成器是一种特殊的函数,它允许我们按需生成一系列值,而无需创建整个集合。当使用生成器生成数组值时,我们可能需要对生成器进行类型提示,以指定返回的数组的类型。然而,这可能是一个挑战,特别是在数组元素具有复杂类型时。

类型提示生成器

要对生成器进行类型提示,我们可以使用 @return 注解,后跟一个泛型类型。泛型类型允许我们在不指定具体类型的情况下指定数组元素的一般类型。例如,以下代码对生成器进行类型提示,以返回字符串和整数的元组数组:

/**
 * @return Generator<array{string, int}>
 */
function myGenerator() {
    yield ['foo', 1];
    yield ['bar', 2];
}

处理复杂的类型

当数组元素具有复杂类型时,例如Doctrine中的 Token 类,对生成器进行类型提示可能会变得更加困难。在这些情况下,我们可以使用泛型约束来指定元素类型的附加条件。例如,以下代码对生成器进行类型提示,以返回包含满足特定条件的令牌数组的元组数组:

/**
 * @template T of UnitEnum|string|int
 * @template V of string|int
 * @return Generator<array{string, Token<T, V>[]}>
 */
function myGenerator() {
    yield ['foo', [new Token(1, Lexer::T_INTEGER, 0)]];
    yield ['bar', [new Token(2, Lexer::T_STRING, 0)]];
}

错误修复

如果您在对生成器进行类型提示时遇到错误,例如:“Generator 期待值类型 array{string, array<Doctrine\Common\Lexer\Token<int, int>>},array{'15', array{Doctrine\Common\Lexer\Token<int, int>} } 给定”,您可以尝试以下方法来解决问题:

  • 确保泛型类型参数正确定义: 验证您的泛型类型参数是否正确指定为 TV,并且它们与 Token 类的模板类型参数匹配。
  • 指定令牌类型的约束: 使用泛型约束,例如 UnitEnum|string|int,来指定令牌类型的附加条件。
  • 确保数组类型的匹配: 验证返回的数组类型与生成器中生成的数组类型的匹配。

常见问题解答

1. 我必须始终指定泛型类型参数吗?

否,您不必始终指定泛型类型参数,但是这样做可以提供额外的类型安全性并提高代码的可读性。

2. 泛型约束有什么作用?

泛型约束允许您指定元素类型必须满足的附加条件。这可以提高代码的安全性,并防止出现无效或不可预期的值。

3. 我可以对其他类型的生成器进行类型提示吗?

是的,您可以在不使用数组的情况下对其他类型的生成器进行类型提示。泛型类型和泛型约束也适用于其他类型的值。

4. 是否有其他方法对生成器进行类型提示?

可以使用 PHPStan 等工具来静态分析您的代码并自动推断生成器的类型。

5. 我可以在哪里了解更多关于生成器类型提示的信息?

您可以参考 PHP 手册PHPStan 文档 以获取更多信息。

结论

对数组值中的生成器进行类型提示对于编写安全可靠的 PHP 代码至关重要。通过利用泛型类型和泛型约束,您可以精确地指定生成器的返回值,并防止出现意外的行为。记住,根据您正在处理的特定类型,解决类型提示错误可能需要一些试验和错误,但遵循上述步骤可以帮助您对您的代码进行类型提示,并提高其安全性。