如何实现支持1-2个泛型参数的TypeScript工厂函数?
实现支持1-2个泛型的工厂函数
需求明确:编写工厂函数createSomeFn,满足两种泛型传入场景:
- 仅传入泛型
R时,返回无参函数() => R; - 传入泛型
R和P时,返回带P类型参数的函数(p: P) => R。
问题分析
你之前给泛型P设默认值never的方案行不通,核心原因是:never是TypeScript中代表「不存在的类型」,当函数参数类型为never时,TS会认为这个函数必须接收一个不可能存在的参数——既不能不传参数,也不能传任何值,直接导致调用报错。
正确解决方案
方案1:函数重载(最直观)
利用TypeScript的函数重载特性,明确声明两种调用场景的签名,再实现兼容两种情况的函数体:
type MapLike = Record<string, any>; // 重载签名1:仅传入R,返回无参函数 function createSomeFn<R extends MapLike>(key: string): () => R; // 重载签名2:传入R和P,返回带P参数的函数 function createSomeFn<R extends MapLike, P extends MapLike>(key: string): (param: P) => R; // 实现签名:兼容两种重载的逻辑 function createSomeFn<R extends MapLike, P extends MapLike = MapLike>( key: string ) { return function (p?: P): R { // 替换为你的实际业务逻辑 return doSomeThing(key, p); } as unknown as (P extends MapLike ? (p: P) => R : () => R); }
方案2:条件类型+泛型默认值
通过条件类型动态判断返回的函数类型,同时把P的默认值设为undefined来代表「无参数」场景:
type MapLike = Record<string, any>; // 根据P是否为undefined,决定返回的函数类型 type ReturnFn<R, P> = P extends undefined ? () => R : (p: P) => R; function createSomeFn<R extends MapLike, P extends MapLike | undefined = undefined>( key: string ): ReturnFn<R, P> { return function (p?: P): R { // 替换为你的实际业务逻辑 return doSomeThing(key, p); } as ReturnFn<R, P>; }
测试验证
仅传入一个泛型(正常工作)
type Re = { bar: string }; const myFn1 = createSomeFn<Re>('myFn'); myFn1(); // ✅ 无报错,符合预期
传入两个泛型(正常工作)
type Pe = { foo: string }; type Re = { bar: string }; const myFn2 = createSomeFn<Re, Pe>('myFn'); // myFn2(); // ❌ 报错:Expected 1 arguments, but got 0(符合预期) myFn2({ foo: 'bar' }); // ✅ 无报错,符合预期
内容的提问来源于stack exchange,提问作者kyon45
相关产品推荐
相关产品推荐

