判别联合类型(Discriminated Unions)是我在日常开发中使用最频繁的 TypeScript 特性。它让复杂的状态建模变得优雅。
基础概念
判别联合由一个共同的字面量字段(判别符)来区分不同的成员。
type ApiState =
| { status: 'idle' }
| { status: 'loading' }
| { status: 'success'; data: T }
| { status: 'error'; message: string };
实战应用
组件中的状态建模
function DataView({ state }: { state: ApiState }) {
switch (state.status) {
case 'idle':
return ;
case 'loading':
return ;
case 'success':
// TypeScript 知道 state.data 存在
return ;
case 'error':
// TypeScript 知道 state.message 存在
return ;
}
}
TypeScript 在每个分支中精确推断类型,这是类型缩窄(Type Narrowing)的完美体现。
事件系统建模
type AppEvent =
| { type: 'USER_LOGIN'; userId: string; timestamp: number }
| { type: 'POST_CREATED'; postId: string; title: string }
| { type: 'COMMENT_ADDED'; commentId: string; postId: string };
function handleEvent(event: AppEvent) {
switch (event.type) {
case 'USER_LOGIN':
console.log(User ${event.userId} logged in);
break;
case 'POST_CREATED':
console.log(New post: ${event.title});
break;
}
}
穷举检查
利用 never 类型确保处理了所有情况:
function assertNever(x: never): never {
throw new Error('Unexpected value: ' + x);
}
function handleEvent(event: AppEvent) {
switch (event.type) {
case 'USER_LOGIN': /* ... */ break;
case 'POST_CREATED': /* ... */ break;
case 'COMMENT_ADDED': /* ... */ break;
default:
assertNever(event); // 如果遗漏了某个 case,这里会报错
}
}
判别联合配合穷举检查,让你的代码在业务逻辑变更时更加健壮。