1️⃣ 定义

穷尽性类型保护是指在处理联合类型、枚举或字面量类型时,确保每一个可能值都被处理到,防止遗漏分支,提升类型安全。

核心手段:利用 never 类型 + 编译器检查。

2️⃣ 为什么用

  • 防止逻辑遗漏:确保联合类型或枚举的每个成员都被处理
  • 增强类型安全:新增联合类型或枚举成员时,TS 会报错
  • 提高可维护性:代码分支清晰,后续扩展安全

3️⃣ 基本写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
type Shape = 'circle' | 'square' | 'triangle'

function handleShape(s: Shape) {
switch(s) {
case 'circle':
// 处理 circle
break
case 'square':
// 处理 square
break
default:
const _exhaustiveCheck: never = s
// TS 编译器会报错,如果还有未处理的类型
}
}
  • _exhaustiveCheck → 任意变量名
  • : never → 告诉 TS:这里应该永远不可能有值
  • 编译器会检查 s 是否剩下未处理的类型

4️⃣ 常见应用场景

  1. switch / if/else 语句
  • 最常见的穷尽性检查方式
  • defaultelse 分支赋值给 never
  1. 函数返回类型检查
1
2
3
4
5
6
7
8
9
10
11
function assertUnreachable(x: never): never {
throw new Error("Unexpected value: " + x)
}

function handleStatus(s: Status) {
switch(s) {
case Status.Success: return ...
case Status.Error: return ...
default: return assertUnreachable(s)
}
}
  • 可复用封装为函数
  • TS 编译器会检查是否遗漏状态
  1. 变量被类型保护缩小到无值
  • 如果联合类型的所有可能值都被排除
  • 剩下的类型被 TS 推断为 never
  1. 枚举类型
  • 数字枚举 / 字符串枚举也可用同样方式检查
  • 防止新增枚举成员导致遗漏逻辑

5️⃣ 技术原理

  • never 类型:永远不可能有值
  • 联合类型 + 类型保护 → 剩余类型可能为 never
  • 赋值给 never → 编译器检查是否真的没有遗漏

6️⃣ 工程实践要点

  1. 适用场景
  • 有有限状态的业务(状态机、UI 状态、表单状态)
  • 枚举或联合类型分支逻辑
  1. 实现方式
  • switch / if/else + never 变量
  • 或封装成 assertUnreachable(x: never) 函数
  1. 好处
  • 编译期发现遗漏分支
  • 逻辑更安全,维护更方便
  • 对新增状态/类型有编译期提示

7️⃣总结

穷尽性类型保护 = 编译器帮你确保联合类型或枚举的每个可能值都被处理,防止遗漏分支。