never类型仅适用于函数绝对不返回控制权的场景,如含throw、exit()、die()或确定无限循环的函数;它不是void(正常结束),而是保证下一行代码不可达,且不可用于联合类型或非终止逻辑中。

never 只该用在「函数执行后绝对不返回控制权给调用方」的场景——不是“可能不返回”,而是语言层强制保证「下一行代码不可达」。
哪些函数适合声明 never
必须满足:函数体内有且仅有以下终止行为之一(或组合),且无任何可能的正常退出路径:
-
throw语句(任意异常,包括throw new RuntimeException()) -
exit()或die()调用(含带状态码的exit(1)) -
trigger_error(..., E_USER_ERROR)且错误处理未被静默捕获 - 明确的无限循环(如
while (true) { }),且编译器能静态确认无break/return
典型例子:abort()、fail()、panic() 这类框架级终止函数;CLI 工具中遇到致命配置错误时的退出函数。
为什么不能随便加 never
PHP 类型系统会做静态验证,一旦声明 never,就必须「实锤」不会返回。常见翻车点:
- 函数里写了
if ($x) { throw ...; }但没处理else分支 → 运行时报Fatal error: Function ... must not return - 调用了
error_log()或echo后没终止 → 类型检查通过,但逻辑上没满足never语义 - 用
return或隐式return null结尾 → 直接语法报错 - 试图在联合类型中用它,比如
string|never→ PHP 解析失败,never不参与联合
never 和 void 的关键区别在哪
这是最容易混淆的地方:
-
void表示「函数结束,不返回值」,控制流正常回到调用处(比如function log(string $msg): void { echo $msg; }) -
never表示「函数不会结束」,控制流永远卡在内部(抛出、退出、死循环),调用它的下一行代码在类型层面被标记为「不可达」 - IDE 和静态分析工具(如 PHPStan)会据此推断后续代码是否冗余。例如:
abort("oops"); echo "unreachable";会被标为 dead code
实际写法要注意什么
声明 never 本身很简单,但要让它真正起作用,得配合运行时行为:
- 别依赖外部副作用判断是否终止,比如
if (file_exists($cfg)) { ... } else { throw ...; }是 OK 的,但if (is_production()) { exit(); }如果is_production()返回bool且未声明never,PHP 无法静态确认分支必然终止 - 避免在
never函数里做资源清理(如fclose()),因为那部分代码可能根本执行不到;清理应放在调用前或用finally块 - 测试时注意:调用
never函数会导致测试进程退出,需用expectException()或重定向stderr捕获,不能靠断言返回值
最常被忽略的是「类型声明和运行时行为必须完全对齐」——never 不是注释,它是 PHP 类型系统的一部分,松一点就会在 CI 或 IDE 中暴露问题。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











