如何定义支持typeof与instanceof混合的多类型Type Guard函数?
实现结合typeof与instanceof的多类型守卫函数
要实现同时支持原始类型(通过typeof字符串)和对象类型(通过构造函数)的多类型检查守卫,需要结合类型映射、实例类型提取和函数重载来完成,具体实现如下:
1. 定义核心类型映射与工具类型
首先创建类型映射表,将typeof返回的字符串类型对应到TypeScript的实际类型;同时定义工具类型提取构造函数的实例类型:
// 映射typeof字符串到对应TypeScript类型 type PrimitiveTypeMap = { string: string; number: number; boolean: boolean; symbol: symbol; undefined: undefined; function: Function; object: object; }; // 提取构造函数的实例类型 type InstanceType<T> = T extends new (...args: any[]) => infer R ? R : never;
2. 实现函数重载与逻辑
通过函数重载分别处理单个类型、多个类型的情况,确保TypeScript能正确推断类型:
// 重载1:检查单个原始类型(传入typeof字符串) function isType<T extends keyof PrimitiveTypeMap>(obj: any, type: T): obj is PrimitiveTypeMap[T]; // 重载2:检查单个对象类型(传入构造函数) function isType<T extends new (...args: any[]) => any>(obj: any, type: T): obj is InstanceType<T>; // 重载3:检查多个类型(支持混合原始类型和对象类型) function isType<T extends (keyof PrimitiveTypeMap | new (...args: any[]) => any)[]>( obj: any, ...types: T ): obj is T[number] extends keyof PrimitiveTypeMap ? PrimitiveTypeMap[T[number]] : InstanceType<T[number]>; // 函数实现 function isType(obj: any, ...types: any[]): boolean { for (const type of types) { // 处理原始类型检查 if (typeof type === 'string') { if (typeof obj === type) return true; } // 处理对象类型的instanceof检查 else if (typeof type === 'function') { if (obj instanceof type) return true; } } return false; }
3. 使用示例
完全匹配你需求的使用场景:
function doSomething(value: any) { let str: string = ""; let num: number = 0; let date: Date | null = null; // 检查单个原始类型 if (isType(value, "string")) { str = value; // TypeScript自动推断value为string } if (isType(value, "number")) { num = value; // 自动推断为number } // 检查对象类型 if (isType(value, Date)) { date = value; // 自动推断为Date } // 多类型联合检查 if (isType(value, "number", Date)) { // 这里value的类型被推断为number | Date if (isType(value, "number")) { date = new Date(date!.getTime() + value); } else { date = value; } } }
为什么之前的泛型实现不生效?
你之前尝试的function typeof<K>(obj: any, type: K): obj is K存在问题:当传入Date时,K会被推断为构造函数类型DateConstructor,而不是实例类型Date。通过InstanceType工具类型可以从构造函数中提取出实际的实例类型,解决这个类型推断偏差的问题。
内容的提问来源于stack exchange,提问作者Nico Richter
相关产品推荐
相关产品推荐

