never类型仅用于函数返回声明,不可作参数、属性或联合类型成员;函数体内必须有throw、exit或死循环等终止行为,否则运行时报错。

never类型只能用在函数返回声明,不能做参数或属性
PHP 的 never 是纯返回类型,语言层面上禁止它出现在任何其他位置。你写 function foo(): never 合法;但 function bar(mixed $x): never 虽然语法通过,$x 本身不能是 never 类型——因为 never 不是值类型,它不描述“传进来什么”,只描述“根本不会回来”。
常见错误现象:
- 给参数加
?never或never|null→ PHP 解析失败,报ParseError - 声明
private never $flag;→ 直接 fatal error:Unknown type never - 在联合类型里混用,如
string|never→ PHP 8.2 明确拒绝,报SyntaxError: Union types cannot contain 'never'
函数体内必须有明确的终止行为,否则运行时报错
never 不是“我懒得写 return”,而是向类型系统承诺:“这函数执行完,控制流绝对不会再往下走”。所以函数体里必须出现至少一个能中断执行的动作。
合法终止方式(三选一即可):
-
throw新异常(如throw new RuntimeException('oops');) -
exit()或die()(含带码退出,如exit(1);) - 死循环(如
while (true) { usleep(1000); }),但生产环境慎用
容易踩的坑:
- 写了
: never却漏了throw/exit,函数末尾隐式返回null→ 运行时报Fatal error: Uncaught Error: Function ... must not return - 用
return提前结束(哪怕后面还有throw)→ 静态分析可能放过,但运行时仍会因实际返回而崩溃 - 条件分支中只在部分路径
throw,其余路径无终止 → 类型系统认为“可能返回”,违反never承诺
别和 void、?null 混用,语义完全相反
void 表示“正常执行完,不返回值”;never 表示“根本执行不完”。两者不可互换,也不能组合。PHPStan 对 ?never 会直接报 nullableType.never 错误,且该错误不可忽略(ignorable: false)。
典型误用场景:
- 想表达“可能失败”,就写
function find(): ?array,而不是function find(): ?never(非法) - 封装一个“失败就终止”的工具函数,应写
function abort(string $msg): never,不是function abort(string $msg): void(后者无法告知调用方“之后代码不可达”) - 框架路由中重定向后需终止,用
header('Location: /'); exit;+: never,而非: void(否则 IDE 不知道后续逻辑不会执行)
配合 PHPStan 做静态保障,别只靠运行时
never 的最大价值在静态分析阶段:它让 PHPStan 能标记出“本不该执行到”的代码块。但前提是你的函数签名和实现严格匹配。
实操建议:
- 所有
: never函数都应被 PHPStan 分析覆盖,确保没漏掉隐式返回 - CI 中开启
--level max,nullableType.never错误必须修复,不能加 ignore - 避免在泛型或高阶函数中返回
never,PHP 8.2 对泛型中never的推导支持有限,易触发误报
最常被忽略的一点:never 函数一旦被调用,其后的所有代码在类型层面都算“不可达”,但 PHP 解释器并不检查这个——它只管执行。真正起作用的是 PHPStan 和 IDE,它们依赖你写的类型声明是否诚实。写错,就等于主动放弃类型安全。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











