判别式(标记)联合体是一组对象类型的联合,它们都共享一个公共文字字段——判别器——编译器用它来区分变体并安全地缩小类型。
ts
type Result =
| { status: "loading" }
| { status: "success"; data: string }
| { status: "error"; message: string };
每个成员都有一个 文字。检查它会将类型缩小到恰好一个变体,解锁该变体的字段:
判别式(标记)联合体是一组对象类型的联合,它们都共享一个公共文字字段——判别器——编译器用它来区分变体并安全地缩小类型。
type Result =
| { status: "loading" }
| { status: "success"; data: string }
| { status: "error"; message: string };
每个成员都有一个 文字。检查它会将类型缩小到恰好一个变体,解锁该变体的字段:
statusfunction render(r: Result) {
switch (r.status) {
case "loading": return "...";
case "success": return r.data; // ✅ data exists only here
case "error": return r.message; // ✅ message exists only here
}
}
如果你尝试在 loading 情况下访问 r.data,这会导致编译错误——类型系统使无效的组合无法表示。
function render2(r: Result): string {
switch (r.status) {
case "loading": return "...";
case "success": return r.data;
case "error": return r.message;
default:
const _exhaustive: never = r; // ✅ if you add a variant and forget a case, this errors
return _exhaustive;
}
}
never 赋值强制你处理每一个情况——添加新的状态,编译器会指出需要更新的每个 switch。
判别式联合体是建模状态(loading/success/error)、事件/操作(Redux reducers)以及任何"多种形状之一"数据的惯用方式。
它们使非法状态成为不可能,并通过 never 技巧,为你提供编译时穷尽性检查——相比松散的 boolean/可选字段建模方式,这是一次巨大的安全胜利。