php 8.2 的 never 类型与 8.1 完全一致,仅在严格模式下生效,要求函数绝对不返回,不可用于联合或可空类型,且函数体必须含 throw/exit/死循环,否则报致命错误;它表示控制流终止,与 void 本质不同。

PHP 8.2 的 never 返回类型用法和 PHP 8.1 完全一致,没有新增行为或语法变化;它只在严格模式下生效,且必须保证函数“真的一次都不返回”。
never 类型只能用于函数返回声明,不能出现在联合类型或可空类型中
你不能写 string|never 或 ?never —— 这两种写法在 PHP 8.2 中仍是语法错误。PHPStan 会直接报 nullableType.never(不可忽略)或解析失败。这是因为 never 是 bottom type(底部类型),逻辑上不可能和任何其他类型共存于联合或可空结构中。
-
function fail(): never { throw new Exception(); }✅ 合法 -
function fail(): string|never { ... }❌ 解析失败:Fatal error -
function fail(): ?never { ... }❌ PHPStan 报nullableType.never,且无法绕过 -
function fail(): mixed|never { ... }❌ 同样非法,never不参与任何联合
函数体内必须有明确的非返回路径,否则运行时报错
声明了 never,但函数体里没 throw、没 exit()/die()、也没死循环?那 PHP 在运行时会直接抛出 Fatal error: Uncaught Error: Function ... must not return。
- 合法示例:
function abort(string $msg): never { throw new RuntimeException($msg); } - 合法示例:
function exit_now(int $code): never { exit($code); } - 合法示例:
function loop(): never { for (;;) {} } - 非法示例:
function bad(): never { return; }→ 触发 PHPStanreturn.never错误 - 非法示例:
function also_bad(): never { echo "hi"; }→ 运行时报 Fatal error
never 和 void 的区别不是“有没有返回值”,而是“控制流是否继续”
void 函数可以正常结束(比如执行完最后一行就返回),只是不带值;never 函数则意味着调用后「当前作用域的后续代码永远不可达」——这是给静态分析器和 IDE 的强契约。
-
function log(string $s): void { echo "$s\n"; }→ 调用后还能继续执行下一行 -
function die_with(string $s): never { echo "$s\n"; exit(1); }→ 调用后下一行永远不会执行(哪怕没写exit(),只要没throw或死循环,就违反语义) - IDE(如 PhpStorm)能据此推断:如果某行前是
never调用,那这行就是 dead code,会标灰或警告 - PHPStan 和 Psalm 依赖这个契约做流程敏感分析,比如判断
if分支后变量是否已定义
最易被忽略的一点:即使函数逻辑上“总会终止”,只要没显式写出 throw/exit/死循环,PHP 就不认;它不推理业务逻辑,只看字面控制流。比如 if (true) { throw ...; } 是 OK 的,但 if ($config['fail']) { throw ...; } 就不行——因为静态分析器无法确认条件恒真。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











