TypeScript中如何仅保留单个of方法,避免联合类型函数重载冗余
解决方案:用条件类型+类型守卫实现单签名of方法
基础类型定义
先明确核心类型:
// 原生双参数函数类型 type FFunction2<T1, T2, R> = (a: T1, b: T2) => R; // 包装器类 class Function2<T1, T2, R> { private fn: FFunction2<T1, T2, R>; private constructor(fn: FFunction2<T1, T2, R>) { this.fn = fn; } apply(a: T1, b: T2): R { return this.fn(a, b); } // 单实现of方法,自动适配原生函数/包装器实例 static of<T extends FFunction2<any, any, any> | Function2<any, any, any>>( fn: T ): T extends FFunction2<infer T1, infer T2, infer R> ? Function2<T1, T2, R> : T { // 运行时类型判断 if (fn instanceof Function2) { return fn as T; } return new Function2(fn) as ReturnType<typeof Function2.of<T>>; } } // 联合类型,统一管理原生函数和包装器 type TFunction2<T1, T2, R> = FFunction2<T1, T2, R> | Function2<T1, T2, R>;
关键逻辑说明
条件类型自动推导:
通过T extends FFunction2<infer T1, infer T2, infer R> ? Function2<T1, T2, R> : T,TypeScript会自动判断传入参数的类型:- 如果是原生
FFunction2,返回包装后的Function2实例; - 如果已经是
Function2实例,直接返回原对象,避免重复包装。
- 如果是原生
运行时类型守卫:
用fn instanceof Function2做运行时判断,确保逻辑分支正确,避免类型断言出错。自动泛型推导:
不需要手动指定泛型参数,TypeScript会从传入的fn自动推导T1、T2、R的类型。
测试示例
// 测试原生函数包装 const add = (a: number, b: number): number => a + b; const wrappedAdd = Function2.of(add); // 自动推导为Function2<number, number, number> console.log(wrappedAdd.apply(2, 3)); // 输出5 // 测试已有包装器实例 const concatWrapper = new Function2((x: string, y: string) => x + y); const sameWrapper = Function2.of(concatWrapper); // 自动推导为Function2<string, string, string> console.log(sameWrapper.apply("hello", " world")); // 输出hello world
扩展到其他参数数量的映射器
如果需要给Function1、Function3等实现同样逻辑,只需复用条件类型+类型守卫的模式,比如把类型守卫抽成通用函数:
function isFunction2Instance<T1, T2, R>(fn: any): fn is Function2<T1, T2, R> { return fn instanceof Function2; }
然后在Function2.of中调用这个函数,代码更易维护。
内容的提问来源于stack exchange,提问作者user731136
相关产品推荐
相关产品推荐

