【通俗易懂】TypeScript 的类型守卫 (Type Guards)作用理解
把“类型守卫”想成安检口的小哥哥/小姐姐:
-
场景
你手里拿了个东西,只知道它是“不明包裹”(联合类型)。
比如:function process(input: string | number) {// 这里 input 是“既可能是 string,也可能是 number” }
-
没有类型守卫 —— 蒙着眼干活
直接写input.length
会报错:
“万一它是数字呢?数字可没有 length!” -
类型守卫 —— 安检口查一查
安检员看一眼包裹,告诉你:“放心,这是字符串!”
于是后面的代码就可以大胆地用字符串的方法了。function isString(x: any): x is string {return typeof x === 'string'; }function process(input: string | number) {if (isString(input)) {// 安检通过,TypeScript 立刻知道 input 现在是 stringconsole.log(input.length); // ✅ 不报错} else {// 走到这里,TypeScript 就知道它是 numberconsole.log(input.toFixed(2)); // ✅ 也不报错} }
-
常见安检手段(类型守卫)
typeof x === 'string'
/typeof x === 'number'
x instanceof Date
- 自定义函数返回
x is SomeType
(上面例子里的isString
)
一句话总结:
类型守卫 = 安检口。
它帮你“看一眼”变量到底是哪种具体类型,通过后 TypeScript 就不再怀疑,让你安心用对应的方法和属性。
这里可能有朋友会有个疑问,这样的话和我们直接写个if else来判断类型又有什么区别呢?
其实区别只有一句话:
“你自己心里知道,但编译器不知道;类型守卫让编译器也知道。”
举个生活场景:
-
没有类型守卫(只有 if/else)
function fn(x: string | number) {if (typeof x === 'string') {// 你清楚 x 是 string,但编译器仍把 x 当成 string | numberconsole.log(x.length); // ❌ 报错:length 可能不存在} }
-
加了类型守卫
function isString(x: any): x is string {return typeof x === 'string'; }function fn(x: string | number) {if (isString(x)) {console.log(x.length); // ✅ 编译器也点头:x 就是 string}// 这里 x 自动变成 number }
所以:
- 普通 if/else 只是运行时的分支判断,TypeScript 的类型系统不会跟着变。
- 类型守卫额外给编译器发了一份“证明”,让它在编译阶段就把类型收窄,你才能安全地调用该类型专属的方法和属性,而不用到处
as string
/as number
强转。