尧图精选

The Concise TypeScript Book:深入理解 `never` 类型——空集语义、穷尽性检查与类型安全实践

🕒 发布时间:2026/9/28 9:18:14 📁 来源:尧图网络
文档教程【免费下载链接】typescript-bookThe Concise TypeScript Book: A Concise Guide to Effective Development in TypeScript. Free and Open Source.项目地址https://gitcode.com/gh_mirrors/typ/typescript-book点击查看免费下载导读本文以《The Concise TypeScript Book》的 Tipo never 章节 为核心系统讲解never类型的语义来源永不返回的函数与抛出错误的表达式、它在控制流分析中的收窄结果以及利用它实现穷尽性检查exhaustiveness checking从而让编译器替你兜底发现未处理分支的实战方法。读完本文你将掌握never的三大核心用途标注永不返回的函数、承接收窄后的“不可能分支”、充当判别联合/switch穷尽性的哨兵类型。never是什么一个代表“永不出现”的类型在 TypeScript 中never类型表示永远不会出现的值values that never occur。它用于标注那些永不返回never return或直接抛出错误throw an error的函数或表达式。从集合论的视角可以更直观地理解它。在 探索类型系统 一节的类型集合表格中never对应的是空集∅——它内部不包含任何成员因此除了它自身之外没有任何类型可以赋值给它反过来因为它是最底层的“空集合”它可以被赋值给任何其他类型。这与unknown全集、string、number等类型的定位形成鲜明对比never是类型层级中最底部、最“窄”的类型。一个经典的反例可以帮助建立直觉let f: never; f 1; // 错误类型 number 不可赋值给类型 never没有任何值能填进一个never类型的变量因为“永不出现的值”在运行时根本不存在。这条看似“没用”的规则恰恰是后续穷尽性检查能够成立的基础。两种产生never的经典函数形态原章节给出了never最常见的两个来源它们都符合“函数体执行不到返回语句”的特征形态一无限循环。循环条件恒为真函数永远无法正常返回const infiniteLoop (): never { while (true) { // faz algo做一些事 } };形态二直接抛出错误。抛错会中断执行流函数同样不会带着返回值结束const throwError (message: string): never { throw new Error(message); };显式标注(): never的价值在于它向 TypeScript 编译器以及阅读代码的人声明“调用该函数后其后续代码在正常情况下永远不会继续执行”。这会让控制流分析control flow analysis得到更精确的结果例如在try/catch或条件分支中throwError(...)之后的语句会被判定为不可达unreachable从而在编译期就暴露出冗余代码或缺失的处理逻辑。never与void容易混淆的两种“无返回”初学者最常把never与 void 类型 混为一谈但二者语义完全不同void表示函数不返回任何值但函数确实会正常结束——它“有返回”只是返回的是undefined意义上的“无”const sayHello (): void { console.log(Hello!); };never表示函数永远无法结束——要么陷入无限循环要么抛出异常根本不存在返回的时机。一句话总结void是“正常结束但不给结果”never是“压根不会结束”。因此void类型的函数调用之后代码还能继续往下走而never类型的调用点之后通常是死代码。控制流收窄到never编译器如何“推”出不可能分支never并不总是需要你手动标注它也会在类型收窄narrowing的过程中被编译器自动推断出来。姊妹章节 O tipo never 给出了这一机制当一个变量被不断收窄直到其类型范围“缩小到不包含任何值”时TypeScript 编译器就会将它的类型推断为never。下面这个例子中string | number的联合类型被typeof逐一收窄后else分支里的val已经没有任何可能的取值const printValue (val: string | number) { if (typeof val string) { console.log(val.toUpperCase()); } else if (typeof val number) { console.log(val.toFixed(2)); } else { // 在这里val 的类型是 never—— // 因为它不可能成为除了 string 或 number 之外的任何东西 const neverVal: never val; console.log(Valor inesperado: ${neverVal}); } };注意最后这个else分支从类型系统看它“必然不可达”但代码在逻辑上仍然存在。此时把val显式声明为never就等于告诉编译器“如果你在这里看到了除never之外的东西说明前面的收窄条件写漏了”。这本质上是一个静态期断言的钩子其意义会在穷尽性检查中完全展开。穷尽性检查用never让switch分支永不遗漏这是never在生产代码中最有实战价值的一个用途原章节用它作为收尾示例而仓库中还有专门的 Verificação de exaustividade 一节展开论述。核心思想在一个switch或if/else链覆盖了联合类型的所有成员之后default分支中的值必然被收窄为never。如果未来有人向联合类型新增了一个成员却忘记添加对应的 case那么新值落入default分支时就不再是neverTypeScript 会立刻抛出编译错误从而在开发阶段拦截遗漏。原章节的示例type Direction up | down; const move (direction: Direction): void { switch (direction) { case up: // move para cima向上移动 break; case down: // move para baixo向下移动 break; default: const exhaustiveCheck: never direction; throw new Error(Direção não tratada: ${exhaustiveCheck}); } };配合穷尽性检查章节的写法逻辑更加清晰type Direction up | down; const move (direction: Direction) { switch (direction) { case up: console.log(Movendo para cima); break; case down: console.log(Movendo para baixo); break; default: const exhaustiveCheck: never direction; console.log(exhaustiveCheck); // 这一行永远不会真正执行 } };这套模式的执行效果当有人把Direction扩展为up | down | left却忘记补case left时default分支里的direction类型会变成leftconst exhaustiveCheck: never direction;这一行随即报错“类型 left 不可赋值给类型 never”错误提示精确地指向未处理的分支配合throw或console.log还能在运行时提供兜底。与判别联合Discriminated Unions组合类型安全的最佳拍档never的穷尽性检查与 判别联合 是天然搭档。判别联合通过一个共同的字面量属性discriminant来区分联合成员例如type Square { kind: square; // 判别属性 size: number; }; type Circle { kind: circle; // 判别属性 radius: number; }; type Shape Square | Circle; const area (shape: Shape) { switch (shape.kind) { case square: return Math.pow(shape.size, 2); case circle: return Math.PI * Math.pow(shape.radius, 2); } };把上文的Direction例子换成Shape这种真实业务对象default: const exhaustiveCheck: never shape;就能在新增Triangle类型时第一时间提醒你补全面积计算。两者结合后“新增类型成员 → 编译报错 → 强制处理新分支”的闭环得以形成这也是大型代码库中保证状态机、协议解析、表单校验等场景安全性的常用手段。never与收窄、unknown的协作边界收窄narrowingnever是收窄的“终点站”。无论是 typeof 守卫、真值收窄、相等性收窄还是in与instanceof所有收窄手段的最终目的都是把联合类型逐步缩小当缩小到空集时编译器自然产出never。穷尽性检查正是站在这个终点上做的最后一道防线。与unknown对比unknown 类型 处于类型层级的最顶端代表“可能是任何类型”使用前必须收窄而never处于最底端代表“不可能是任何类型”。二者一顶一底共同构成了 TypeScript 类型系统的两个极端锚点。strictNullChecks的关联探索类型系统 中提到当strictNullChecks开启时null与undefined会被当作类似void的独立类型处理关闭时它们的表现则更接近never。也就是说strictNullChecks的开关会直接影响空值在收窄与赋值规则中的行为进而影响never相关代码的判定结果建议在tsconfig.json中开启它以获得最严格的保护。小结never的三种典型用途标注永不返回的函数无限循环、throw、process.exit等场景返回类型写成never让控制流分析识别不可达代码承接收窄后的不可能分支在if/else链的兜底分支把变量声明为never把“逻辑矛盾”显式呈现给编译器充当穷尽性检查的哨兵在switch的default分支用const check: never x;强制要求联合类型的每个成员都有对应处理让新增类型成员时的遗漏在编译期即被捕获。never是 TypeScript 中少见的“用类型系统表达不可能性”的工具理解并熟练运用它是写出高健壮性、可演进的类型安全代码的重要一步。延伸阅读均出自本仓库葡萄牙语版书籍章节Verificação de exaustividade O tipo never Tipo void Uniões Discriminadas Estreitamento (Narrowing) Explorando o sistema de tipos赞分享文档教程【免费下载链接】typescript-bookThe Concise TypeScript Book: A Concise Guide to Effective Development in TypeScript. Free and Open Source.项目地址https://gitcode.com/gh_mirrors/typ/typescript-book点击查看免费下载相关推荐The Concise TypeScript Book深入理解 never 类型与穷尽性检查The Concise TypeScript Book深入理解 never 类型与穷尽性检查 导读 never 是 TypeScript 类型系统中一个容易误文档教程The Concise TypeScript Book 精读深入理解 never 类型与穷尽性检查The Concise TypeScript Book 精读深入理解 never 类型与穷尽性检查 never 类型是 TypeScript 类型系统中一个看文档教程The Concise TypeScript Book 精讲深入理解 never 类型与穷尽性检查实战The Concise TypeScript Book 精讲深入理解 never 类型与穷尽性检查实战 never 是 TypeScript 内置类型中最特殊文档教程上一篇国家中小学智慧教育平台电子课本下载工具三步获取教材PDF的终极方案下一篇HVE Core文档自动生成指南Generate-AssetDocs脚本实战创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联 返回资讯列表 →