类型参考¶
为了防止类型注释的冲突或重复,该库尝试处理 [PHPStan] 和 [Psalm] 接受的大多数类型注释。
提示
当属性、参数或返回类型使用库尚无法解析的 PHPStan 或 Psalm 语法时,例如条件类型($a is 1 ? int : null) ,专用的@valinor-var 、 @valinor-param和@valinor-return注释可用于为库提供它理解的类型。它们优先于所有其他注释,因此静态分析工具在库使用覆盖时继续使用它们自己的类型:
标量¶
final readonly class SomeClass
{
public function __construct(
public bool $boolean,
public float $float,
public int $integer,
/** @var positive-int */
public int $positiveInteger,
/** @var negative-int */
public int $negativeInteger,
/** @var non-positive-int */
public int $nonPositiveInteger,
/** @var non-negative-int */
public int $nonNegativeInteger,
/** @var int<-42, 1337> */
public int $integerRange,
/** @var int<min, 0> */
public int $integerRangeWithMinRange,
/** @var int<0, max> */
public int $integerRangeWithMaxRange,
public string $string,
/** @var non-empty-string */
public string $nonEmptyString,
/** @var numeric-string */
public string $numericString,
/** @var class-string */
public string $classString,
/** @var class-string<SomeInterface> */
public string $classStringOfAnInterface,
/** @var value-of<SomeEnum> */
public string $valueOfEnum,
/** @var scalar */
public bool|string|int|float $scalar,
) {}
}
对象¶
final readonly class SomeClass
{
public function __construct(
public SomeClass $class,
public DateTimeInterface $interface,
/** @var SomeInterface&AnotherInterface */
public object $intersection,
/** @var SomeCollection<SomeClass> */
public SomeCollection $classWithGeneric,
) {}
}
/**
* @template T of object
*/
final readonly class SomeCollection
{
public function __construct(
/** @var array<T> */
public array $objects,
) {}
}
泛型¶
类可以使用@template注解声明模板类型;当引用该类时,它们会被填充为具体类型。模板可以使用of绑定到类型,并且可以使用=声明默认类型。
引用类时可以省略声明默认类型的模板,在这种情况下将使用默认类型。未声明的模板必须始终填写。
final readonly class SomeUser
{
public function __construct(
public string $name,
) {}
}
/**
* @template TValue
* @template TMeta of array<string, mixed> = array<string, string>
*/
final readonly class SomePage
{
public function __construct(
/** @var list<TValue> */
public array $items,
/** @var TMeta */
public array $meta,
) {}
}
final readonly class SomeClass
{
public function __construct(
// `TMeta` is not filled in, its default type is used
/** @var SomePage<SomeUser> */
public SomePage $pageWithDefaultMeta,
// `TMeta` is filled in, overriding its default type
/** @var SomePage<SomeUser, array{cursor: int}> */
public SomePage $pageWithCursorMeta,
) {}
}
声明默认类型的模板必须放在最后:没有默认类型的模板不能在具有默认类型的模板之后声明。当有一个默认类型时,默认类型还必须与使用of声明的边界相匹配。
注意
默认类型使得可以将模板添加到已在其他地方引用的类中:现有的引用不会填充新模板,继续解析为其默认类型,并且可以在以后变得更加精确。
数组和列表¶
final readonly class SomeClass
{
public function __construct(
/** @var string[] */
public array $simpleArray,
/** @var array<string> */
public array $arrayOfStrings,
/** @var array<string, SomeClass> */
public array $arrayOfClassWithStringKeys,
/** @var array<int, SomeClass> */
public array $arrayOfClassWithIntegerKeys,
/** @var array<non-empty-string, string> */
public array $arrayOfClassWithNonEmptyStringKeys,
/** @var array<'foo'|'bar', string> */
public array $arrayOfClassWithStringValueKeys,
/** @var array<42|1337, string> */
public array $arrayOfClassWithIntegerValueKeys,
/** @var array<positive-int, string> */
public array $arrayOfClassWithPositiveIntegerValueKeys,
/** @var non-empty-array<string> */
public array $nonEmptyArrayOfStrings,
/** @var non-empty-array<string, SomeClass> */
public array $nonEmptyArrayWithStringKeys,
/** @var list<string> */
public array $listOfStrings,
/** @var non-empty-list<string> */
public array $nonEmptyListOfStrings,
/** @var array{foo: string, bar: int} */
public array $shapedArray,
/** @var array{foo: string, bar?: int} */
public array $shapedArrayWithOptionalElement,
/** @var array{string, bar: int} */
public array $shapedArrayWithUndefinedKey,
/** @var array{foo: string, ...} */
public array $unsealedShapedArray,
/** @var array{foo: string, ...array<string>} */
public array $unsealedShapedArrayWithExplicitType,
/** @var array{foo: string, ...array<int, string>} */
public array $unsealedShapedArrayWithExplicitKeyAndType,
/** @var array{foo: string, ...<string>} */
public array $unsealedShapedArrayWithShorthandType,
/** @var array{foo: string, ...<int, string>} */
public array $unsealedShapedArrayWithShorthandKeyAndType,
/** @var list{string, int, float} */
public array $shapedList,
/** @var list{0: string, 1: int} */
public array $shapedListWithExplicitKeys,
/** @var list{0: string, 1?: int} */
public array $shapedListWithOptionalElement,
/** @var list{string, int, ...} */
public array $unsealedShapedList,
/** @var list{string, int, ...list<float>} */
public array $unsealedShapedListWithExplicitType,
/** @var list{string, ...<float>} */
public array $unsealedShapedListWithShorthandType,
) {}
}
联合类型¶
final readonly class SomeClass
{
public function __construct(
public int|string $simpleUnion,
/** @var class-string<SomeInterface|AnotherInterface> */
public string $unionOfClassString,
/** @var array<SomeInterface|AnotherInterface> */
public array $unionInsideArray,
/** @var int|true */
public int|bool $unionWithLiteralTrueType,
/** @var int|false */
public int|bool $unionWithLiteralFalseType,
/** @var 404.42|1337.42 */
public float $unionOfFloatValues,
/** @var 42|1337 */
public int $unionOfIntegerValues,
/** @var 'foo'|'bar' */
public string $unionOfStringValues,
) {}
}
类常量¶
final readonly class SomeClassWithConstants
{
public const FOO = 1337;
public const BAR = 'bar';
public const BAZ = 'baz';
}
final readonly class SomeClass
{
public function __construct(
/** @var SomeClassWithConstants::FOO|SomeClassWithConstants::BAR */
public int|string $oneOfTwoCasesOfConstants,
/** @param SomeClassWithConstants::BA* (matches `bar` or `baz`) */
public string $casesOfConstantsMatchingPattern,
) {}
}
枚举¶
enum SomeEnum
{
case FOO;
case BAR;
case BAZ;
}
final readonly class SomeClass
{
public function __construct(
public SomeEnum $enum,
/** @var SomeEnum::FOO|SomeEnum::BAR */
public SomeEnum $oneOfTwoCasesOfEnum,
/** @var SomeEnum::BA* (matches BAR or BAZ) */
public SomeEnum $casesOfEnumMatchingPattern,
) {}
}
key-of / value-of¶
key-of<T>和value-of<T>类型从枚举、数组、列表和指定结构的数组(包括数组常量)中提取键或值类型。它们与 [PHPStan] 和 [Psalm] 接受的相同语法兼容。
key-of¶
enum SomePureEnum
{
case FOO;
case BAR;
}
enum SomeBackedEnum: string
{
case FOO = 'foo';
case BAR = 'bar';
}
final readonly class SomeClassWithConstants
{
public const SOME_ARRAY = ['foo' => 1, 'bar' => 2];
}
final readonly class SomeClass
{
public function __construct(
// Accepts 'FOO' or 'BAR' (the case names of the enum)
/** @var key-of<SomePureEnum> */
public string $pureEnumKey,
// Also works with backed enums — still yields the case *names*
/** @var key-of<SomeBackedEnum> */
public string $backedEnumKey,
// Accepts 'foo' or 'bar' (the keys of the shaped array)
/** @var key-of<array{foo: string, bar: int}> */
public string $shapedArrayKey,
// Accepts the key type of the array (string here)
/** @var key-of<array<string, int>> */
public string $arrayKey,
// Accepts the key type of the list (always int)
/** @var key-of<list<string>> */
public int $listKey,
// Accepts 'foo' or 'bar' (the keys of the class constant array)
/** @var key-of<SomeClassWithConstants::SOME_ARRAY> */
public string $constantArrayKey,
) {}
}
value-of¶
enum SomeBackedStringEnum: string
{
case FOO = 'foo';
case BAR = 'bar';
}
final readonly class SomeClassWithConstants
{
public const SOME_ARRAY = ['foo' => 1, 'bar' => 2];
}
final readonly class SomeClass
{
public function __construct(
// Accepts 'foo' or 'bar' (the backed values of the enum)
/** @var value-of<SomeBackedStringEnum> */
public string $enumValue,
// Accepts string or int (the union of value types in the shaped array)
/** @var value-of<array{foo: string, bar: int}> */
public string|int $shapedArrayValue,
// Accepts the value type of the array (SomeOtherClass here)
/** @var value-of<array<string, SomeOtherClass>> */
public SomeOtherClass $arrayValue,
// Accepts the element type of the list (string here)
/** @var value-of<list<string>> */
public string $listValue,
// Accepts 1 or 2 (the values of the class constant array)
/** @var value-of<SomeClassWithConstants::SOME_ARRAY> */
public int $constantArrayValue,
) {}
}