类型守卫的核心作用是在分支中让 typescript 编译器“看清”变量的真实类型,从而允许安全调用对应类型的属性或方法;typeof 适用于原始类型,instanceof 适用于类实例,二者需配合使用并遵循顺序与语法规范。

类型守卫的核心作用是在分支中让 TypeScript 编译器“看清”变量的真实类型,从而允许安全调用对应类型的属性或方法。typeof 和 instanceof 是最常用、最可靠的两类守卫,它们分别适用于基础类型和类实例场景,关键在于条件判断必须能被编译器静态识别。
typeof 守卫:精准识别原始类型
它只对 JavaScript 原始类型有效(string / number / boolean / bigint / symbol / undefined),不能区分对象或自定义类。一旦条件成立,编译器会将变量类型缩小为对应的具体原始类型。
- 写法必须是 typeof 变量 === "类型字符串",比如
typeof value === "string";用!==或其他表达式(如typeof value == "string")无法触发缩小 - 联合类型如
string | number | boolean,每个分支都能获得唯一子类型,可直接调用.toUpperCase()、.toFixed()、? "true" : "false"等专属方法 - 注意:
typeof null返回"object",所以typeof x === "object"不能断定 x 是对象实例,也可能为 null;需额外检查x !== null
instanceof 守卫:准确识别类构造器实例
它依赖运行时的原型链判断,只适用于通过 class 或构造函数创建的对象。当条件成立时,变量类型会被缩小为该类及其子类的精确类型。
- 语法是 变量 instanceof 构造函数名,例如
item instanceof Date或obj instanceof CustomError - 支持继承关系:若
Dog extends Animal,则dog instanceof Animal为 true,且分支内dog类型会缩小为Animal(不是Dog),除非用instanceof Dog - 不能用于普通对象字面量或内置类型如
Array、RegExp的精确识别(虽然arr instanceof Array有效,但更推荐用Array.isArray()避免跨 iframe 问题)
两者配合使用更稳妥
实际项目中常遇到混合类型,比如参数可能是字符串、数字或某个 Error 子类。这时可以先用 typeof 排除原始类型,再用 instanceof 处理对象分支。
- 例如处理
error: string | number | Error:先typeof error === "string",再typeof error === "number",最后error instanceof Error - 顺序很重要:把最具体的守卫放前面,避免遗漏;TypeScript 会按 if-else 链顺序逐级缩小,确保每个分支类型唯一
- 不要混用守卫与类型断言——守卫是运行时检查+编译时推导,断言只是强制告诉编译器“信我”,没有安全性保障
常见误区提醒
守卫失效往往不是语法错,而是逻辑设计问题。
-
if (x)这类真值判断不会触发类型缩小,除非变量类型本身含null或undefined,此时属于“真值缩小”,和typeof无关 -
in操作符虽也是守卫,但它基于属性存在性,不适用于typeof或instanceof的语义场景;三者定位不同,别强行替代 - 箭头函数或异步回调中,守卫作用域仅限当前块;若把守卫结果赋给新变量,需确保新变量类型声明明确,否则缩小效果不延续











