TypeScript 联合类型、收窄与类型守卫
解释联合类型如何表达多种可能,以及控制流和类型守卫如何在使用前缩小类型范围。
#type / concept
#status / evergreen
#tech / dev
#resource / typescript
[!info] related notes
- 路线:TypeScript 学习路线
- 状态建模:TypeScript 可辨识联合与穷尽检查
- 外部输入:TypeScript 静态类型与运行时校验
TypeScript 联合类型、收窄与类型守卫
一句话定义
联合类型表示一个值可能属于多个成员;收窄利用运行时检查和控制流,证明当前分支中只剩更具体的成员。
function messageOf(error: unknown): string {
if (error instanceof Error) {
return error.message;
}
return String(error);
}
内置收窄方式
typeof value === 'string'value instanceof Error'field' in valuevalue !== null- 等值比较
- 数组和库提供的判定函数,如
Array.isArray
收窄必须对应真实的运行时证据。as SomeType 不做检查,因此不是类型守卫。
自定义类型谓词
function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === 'object' && value !== null && !Array.isArray(value);
}
谓词中的实现必须真的足以证明返回类型。只返回 true 或只检查一个无关字段,会把错误转移到运行时。
控制流分析
提前返回能让后续代码自然收窄:
function requireRunId(value: string | undefined): string {
if (!value) throw new Error('run id is required');
return value;
}
常见误解
- 真值判断会同时排除
''、0、false,不一定等价于判空。 in只能证明属性存在,不能证明属性值的完整结构。- 类型守卫验证多少,返回类型就只能承诺多少。