编程

PHP 8.2 新特性 — true 类型

1165 2022-11-15 07:36:10

PHP 8.2 允许将 true 作为单独的类型使用,也可以作为联合类型的一部分。

  • PHP 7.0 添加了标量类型支持,比如 stringintbool,扩展了 PHP 类型表达式。
  • PHP 8.0 引入了联合类型,false 也作为联合类型的一部分引入。
  • PHP 8.2 起,可以把 truenullfalse 作为单独的类型使用。

PHP 8.2 起,true 可以在任何接收类型的地方作为类型使用:

class Foo {

    private true $processed;

    public function process(string|int|true $value): true {
    }
}

true 类型非强制转换

参数、属性或者返回类型被声明为 true 时,PHP 并不会强制将其他类型转化为 true。即使 PHP 脚本禁用严格类型(strict_types), 且即使值在非严格比较下会被转换为 true,都是这种情况。

比如,以下函数调用不强制将整数值 1 转换为 true,且会导致类型错误 TypeError

function foo(true $value) {}

foo(1);
TypeError: foo(): Argument #1 ($value) must be of type true, int given, called in ... on line ... and defined in ...:...

在联合类型使用 true 

true 类型可以作为联合类型的一部分,只要 true 类型不冗余或者不是与 false 类型同时使用。

下面是使用 true 类型作为联合类型的例子:

function sendEmail(true|string): true {
    return true;
}

sendEmail(true);

PHP 的 bool 类型本质上是 true|false 联合类型。不过,为了避免含混不清,以下两种约束是强制的。

布尔类型的冗余检测

true 类型不能与 bool 类型一起组成联合类型,因为 bool 类型已经包含了 true 类型。尝试声明会导致编译时致命错误:

function foo(true|bool $value) {}
Fatal error: Duplicate type true is redundant in ... on line ...

不允许 true|false 联合类型

由于 bool 类型本质上就是 true|false,所以不允许使用 true|false 作为联合类型:

function foo(true|false $value) {}
Fatal error: Type contains both true and false, bool should be used instead in ... on line ...

在交叉类型中使用 true 类型

true 类型也不能用于交叉类型(Inspection type)。使用 true 类型作为交叉类型会出现编译时错误:

function foo(true&false $value) {}
Fatal error: Type true cannot be part of an intersection type in ... on line ...

true Type 方差 

true 类型被当作 bool 类型的子类型,PHP 遵循标准的协方差和逆变规则,对 true 类型同样适用。

方差规则的例子中,返回类型为 booltrue 类型所取代,联合类型在子类中被缩小了。

class Foo {
    public function test(): bool {}
    public function test2(): string|true {}
}

class FooBar extends Foo {
    public function test(): false {}
    public function test2(): true {}
}

逆变规则的例子中, ture 类型参数被扩展至 bool 类型,联合类型也被扩展了:

class Foo {
    public function test(true $value): void {}
    public function test2(true|string $value): void {}
}

class FooBar extends Foo {
    public function test(bool $value): void {}
    public function test2(true|string|int $value): void {}
}

向后兼容性影响

true 是 PHP 保留的关键词,在 PHP 8.2 中添加 true 作为有效类型不会导致已有应用的任何兼容问题。

注意,PHP 8.2 以前的版本不能将 true 类型作为单独类型或联合类型使用,会导致编译时致命错误:

Fatal error: Cannot use 'true' as class name as it is reserved in ... on line ...

需要使用 true 类型的 PHP 应用,要添加表达式可以使用 PHPDoc 注释,并诉诸于使用 bool 类型来兼容老版本 PHP:

/**
 * @param true $value
 */
function foo(true $value) {}