You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现支持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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 18:30:33