联合类型 let x: string | number 的问题是:你不知道当前是哪一个,只能调用两者共有的方法。类型守卫就是「检查 + 窄化」:if (typeof x === "string") 分支内 x 自动变成 string,TS 编译器理解这个条件并收窄类型。这就是「类型缩小(narrowing)」。
常用守卫:typeof(原始类型)、instanceof(类实例)、in(属性是否存在)、自定义类型谓词(x is Type)。其中「自定义谓词」是王者:function isUser(x): x is User 一旦返回 true,调用处 x 就是 User,是处理复杂联合类型的标配手段。
type Result = { code: number } | { error: string };
// 1) in 守卫:看属性判别
function handle(r: Result) {
if ('error' in r) {
console.log(r.error); // 这里 r 被缩小为错误分支
} else {
console.log(r.code); // 缩小为成功分支
}
}
// 2) 自定义类型谓词
function isString(x: unknown): x is string {
return typeof x === 'string';
}
const v: unknown = 'abc';
if (isString(v)) v.toUpperCase(); // v 已是 string
// 3) typeof / instanceof
function f(x: string | number, d: Date) {
if (typeof x === 'string') x.length; // x: string
if (d instanceof Date) d.getTime(); // ✓
}