若instanceof仅支持类,如何为TypeScript类型实现类型守卫?
如何为TypeScript的type类型实现类型守卫?
问题背景
TypeScript中,instanceof操作符仅支持检查类的实例(因为类在运行时存在对应的构造函数值),但对于type定义的类型(比如字面量联合类型、对象类型等),直接使用instanceof会报错——因为type只是编译时类型别名,不存在于运行时环境中,无法作为instanceof的右操作数。
例如以下代码会抛出错误:
type Letter = 'A' | 'B'; // 错误:'Letter'仅指代类型,但被当作值使用 const isLetter = (c: any): c is Letter => c instanceof Letter;
而类的场景下instanceof可以正常工作:
class Car {} const isCar = (c: any): c is Car => c instanceof Car; // 无错误 isCar('a'); // 返回false
解决方案:自定义运行时检查逻辑
对于type类型,需要在类型守卫函数中手动实现运行时的类型检查逻辑,同时通过参数名 is 类型名的返回类型注解,让TypeScript识别这是一个类型守卫。
1. 字面量联合类型
针对像Letter这样的字面量联合类型,直接枚举所有可能的取值,在运行时检查值是否属于该集合:
type Letter = 'A' | 'B' | 'a' | 'b'; // 匹配你预期的大小写范围 const isLetter = (c: any): c is Letter => { return ['A', 'B', 'a', 'b'].includes(c); }; // 用法示例 isLetter('a'); // 返回true 'foo bar'.split('').filter(isLetter); // 返回['a']
2. 对象类型
对于对象结构的type,需要检查对象的存在性以及各个属性的类型:
type User = { id: number; name: string; }; const isUser = (obj: any): obj is User => { // 先确保是对象且不为null,再检查属性类型 return typeof obj === 'object' && obj !== null && typeof obj.id === 'number' && typeof obj.name === 'string'; };
3. 复杂联合类型
如果是包含多种结构的联合类型,可以针对每个分支分别检查:
type Shape = | { type: 'circle'; radius: number } | { type: 'rectangle'; width: number; height: number }; const isShape = (obj: any): obj is Shape => { if (typeof obj !== 'object' || obj === null) return false; switch (obj.type) { case 'circle': return typeof obj.radius === 'number'; case 'rectangle': return typeof obj.width === 'number' && typeof obj.height === 'number'; default: return false; } };
核心原理
TypeScript的type仅存在于编译阶段,编译完成后会被完全擦除,无法在运行时直接引用。因此类型守卫的本质是用运行时可执行的代码,模拟编译时的类型约束,同时通过c is Letter这样的注解,告诉TypeScript在函数返回true时,参数的类型可以被收窄为目标类型。
内容的提问来源于stack exchange,提问作者surajs02
相关产品推荐
相关产品推荐

