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

TypeScript中如何复用推断参数类型实现链式API避免重复?

解决TypeScript链式API的类型上下文积累问题

核心方案:用泛型跟踪已积累的类型

把Chain接口定义为带泛型参数的结构,泛型参数专门存储每次调用bravo时推断出的参数类型集合。每次调用bravo时,将新推断的类型追加到泛型集合中,并返回携带新泛型参数的Chain实例,以此实现类型上下文的递归传递,完全避免手动重复定义返回类型。

具体实现代码

// 泛型Accumulated存储已积累的类型,默认值为空数组
interface Chain<Accumulated extends unknown[] = []> {
  // bravo方法自动推断参数类型T,返回的Chain泛型参数追加T到原集合
  bravo<T>(xs: T): Chain<[...Accumulated, T]>;
  
  // 可选:添加方法验证积累的类型是否正确
  getAccumulatedTypes(): Accumulated;
}

// 实现Chain接口的具体类
class ChainImpl<Accumulated extends unknown[] = []> implements Chain<Accumulated> {
  bravo<T>(xs: T): Chain<[...Accumulated, T]> {
    return new ChainImpl<[...Accumulated, T]>() as Chain<[...Accumulated, T]>;
  }

  getAccumulatedTypes(): Accumulated {
    return [] as unknown as Accumulated;
  }
}

// 使用示例
const chain = new ChainImpl()
  .bravo(123) // 自动推断T为number,返回Chain<[number]>
  .bravo('hello') // 自动推断T为string,返回Chain<[number, string]>
  .bravo(true); // 自动推断T为boolean,返回Chain<[number, string, boolean]>

// 验证类型:AccumulatedTypes会被推断为[number, string, boolean]
type AccumulatedTypes = ReturnType<typeof chain.getAccumulatedTypes>;

关键细节说明

  • 泛型参数Accumulated:用数组类型存储每次调用的参数类型,通过扩展运算符[...Accumulated, T]实现类型的无缝追加,无需手动维护类型列表。
  • 自动类型推断:每次调用bravo时,TypeScript会自动识别参数xs的类型T,并自动更新返回的Chain泛型参数,全程无需手动指定类型。
  • 代码简洁性:所有类型积累逻辑通过泛型递归传递实现,彻底告别重复写返回类型的冗余代码,可读性和可维护性大幅提升。

扩展:访问积累的类型做业务处理

如果链式API需要在后续方法中使用已积累的类型,可以直接借助泛型参数Accumulated:

interface Chain<Accumulated extends unknown[] = []> {
  bravo<T>(xs: T): Chain<[...Accumulated, T]>;
  // 用Accumulated类型约束回调参数
  process(callback: (values: Accumulated) => void): void;
}

class ChainImpl<Accumulated extends unknown[] = []> implements Chain<Accumulated> {
  private accumulated: Accumulated = [] as unknown as Accumulated;

  bravo<T>(xs: T): Chain<[...Accumulated, T]> {
    const newAccumulated = [...this.accumulated, xs] as [...Accumulated, T];
    const newChain = new ChainImpl<[...Accumulated, T]>();
    newChain.accumulated = newAccumulated;
    return newChain;
  }

  process(callback: (values: Accumulated) => void): void {
    callback(this.accumulated);
  }
}

// 使用示例
new ChainImpl()
  .bravo(123)
  .bravo('hello')
  .process(values => {
    // values类型自动推断为[number, string],可直接调用对应类型的方法
    console.log(values[0].toFixed(2));
    console.log(values[1].toUpperCase());
  });

内容的提问来源于stack exchange,提问作者Jason Kuhrt

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 12:17:35