TypeScript 中联合类型的辨识与穷尽检查通过字面量判别字段(如 type)实现类型收窄,并借助 never 类型的 default 分支强制编译期穷尽性校验;判别字段须为字面量类型,避免使用 string 或未冻结 enum;可配合类型守卫提升可读性与复用性。

在 TypeScript 中处理联合类型时,辨识(discrimination)和穷尽检查(exhaustiveness checking)是确保类型安全的关键手段。核心思路是:通过一个公共的、字面量类型的字段(称为“判别字段”或 discriminant)来区分联合成员,并借助 TypeScript 的控制流分析与 never 类型实现编译期的穷尽性保障。
使用字面量联合类型作为判别字段
最常见也最推荐的方式是定义一个具有唯一字面量值的字段(如 type 或 kind),让每个联合成员都拥有该字段的不同字面量类型。TypeScript 能据此缩小类型范围。
例如:
type Action =| { type: "FETCH_START"; url: string }
| { type: "FETCH_SUCCESS"; data: any }
| { type: "FETCH_ERROR"; error: Error };
此时 type 就是判别字段。TypeScript 在 switch 或 if-else 中检查 action.type 时,能自动推导出对应分支的精确类型。
立即学习“Java免费学习笔记(深入)”;
用 switch + exhaustive check 防止遗漏
仅靠判别字段还不够——如果新增一种类型但忘记处理,运行时可能出错。可通过返回 never 的默认分支强制编译器报错,从而实现穷尽检查。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
写法示例:
function handleAction(action: Action) {switch (action.type) {
case "FETCH_START":
console.log("loading:", action.url);
break;
case "FETCH_SUCCESS":
console.log("data:", action.data);
break;
case "FETCH_ERROR":
console.error("failed:", action.error);
break;
default:
const _exhaustiveCheck: never = action;
throw new Error(`Unhandled action: ${_exhaustiveCheck}`);
}
}
当向 Action 添加新成员(如 { type: "FETCH_CANCEL" })后,default 分支中赋值 _exhaustiveCheck 会报错:Type '...' is not assignable to type 'never',提示你补全处理逻辑。
避免非字面量判别字段导致的类型收窄失效
判别字段必须是字面量类型(如 "FETCH_START"),不能是 string、enum(未启用 const enum 或未用 as const)、或动态计算值,否则 TypeScript 无法安全收窄。
- ❌ 错误:用普通
string字段 —— 无法区分不同成员 - ❌ 错误:用未冻结的
enum—— 编译后是数字,失去语义 - ✅ 正确:用
as const声明对象,或直接写字符串字面量 - ✅ 正确:用
const enum(需开启preserveConstEnums: false)或declare const确保字面量类型保留
配合类型守卫提升可读性与复用性
对复杂联合类型,可封装类型守卫函数(type guard),显式声明判断逻辑,既增强可读性,又便于多处复用。
function isFetchStart(action: Action): action is Extract<Action, { type: "FETCH_START" }> {return action.type === "FETCH_START";
}
之后可用 if (isFetchStart(action)) { ... } 安全访问 action.url,且 TypeScript 会自动收窄类型。
不复杂但容易忽略。

















