如何在TypeScript中实现检查类型相等的IsEqual工具类型?
实现TypeScript的类型等价检测工具类型
IsEqual 要实现一个能准确判断两个类型是否完全等价的工具类型,核心是利用TypeScript泛型函数类型的兼容性特性——只有当两个类型的结构和行为完全一致时,对应的泛型函数类型才会被视为兼容。
核心实现
type IsEqual<Type1, Type2> = (<T>() => T extends Type1 ? 1 : 2) extends (<T>() => T extends Type2 ? 1 : 2) ? true : false;
原理说明
通过定义两个泛型函数类型,它们的返回值逻辑是:若泛型参数T继承自目标类型则返回1,否则返回2。
- 如果
Type1和Type2完全等价,那么这两个函数类型的行为完全一致,TypeScript会判定它们兼容,最终返回true。 - 若两个类型存在差异(比如
any和string、number和1),函数类型的行为会出现分歧,最终返回false。
适配你的重载场景
结合你给出的函数重载需求,IsAmbiguous类型可以直接基于IsEqual实现:
type IsAmbiguous<T> = T extends { isString: infer K } ? IsEqual<K, boolean> extends true ? T : never : never; // 重载函数定义 function doThing(val: number, opts: { isString: true }): string; function doThing(val: number, opts: { isString: false }): number; function doThing<T>(val: number, opts: IsAmbiguous<T>): string | number; // 运行时实现 function doThing(val: number, opts: { isString: boolean }): string | number { return opts.isString ? String(val) : val; }
这个实现可以准确区分三种调用场景:
- 传入
{ isString: true }时,匹配第一个重载,返回类型为string; - 传入
{ isString: false }时,匹配第二个重载,返回类型为number; - 传入类型为
{ isString: boolean }的变量时,匹配第三个重载,返回类型为string | number。
边缘情况验证
这个IsEqual实现能处理大部分常见的边缘场景:
IsEqual<{ a: number }, { a: number }>→true(结构完全一致)IsEqual<boolean, true | false>→true(布尔类型等价于真假联合类型)IsEqual<any, string>→false(any与具体类型不等价)IsEqual<never, never>→true(never类型自身等价)IsEqual<1 | 2, 2 | 1>→true(联合类型的顺序不影响等价性)
内容的提问来源于stack exchange,提问作者Andrew Philips
相关产品推荐
相关产品推荐

