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

如何为TypeScript链式模块定义类型以保证中间类型匹配?

实现类型安全的ModuleChain链式集合

首先定义基础的Module类型:

type Module<TInput, TOutput> = {
  passThrough: (input: TInput) => TOutput;
};

需求说明

需要创建ModuleChain类型,用于存储上述模块的链式集合,要求链中相邻模块的输出/输入类型必须匹配:

  • 合法示例:[Module<string, number>, Module<number, Date>, Module<Date, string>]
  • 非法示例:[Module<string, number>, Module<Date, string>](中间类型不匹配)

以下提供两种可行方案:


方案一:扁平数组版本(只读元组)

利用TypeScript的递归条件类型和可变元组类型,可以定义出类型安全的数组版ModuleChain:

type ModuleChain<TInput, TOutput> = 
  // 基础情况:单个模块,直接匹配输入输出类型
  readonly [Module<TInput, TOutput>] 
  // 递归情况:第一个模块的输出作为后续链的输入
  | readonly [Module<TInput, infer TIntermediate>, ...ModuleChain<TIntermediate, TOutput>];

使用示例

const moduleA: Module<string, number> = { passThrough: (s) => parseInt(s) };
const moduleB: Module<number, Date> = { passThrough: (n) => new Date(n) };
const moduleC: Module<Date, string> = { passThrough: (d) => d.toISOString() };
const moduleD: Module<string, string> = { passThrough: (s) => s.toUpperCase() };

// 合法:类型匹配
const chain1: ModuleChain<string, string> = [moduleA, moduleB, moduleC, moduleD];
const chain2: ModuleChain<string, Date> = [moduleA, moduleB];

// 非法:类型不匹配,TypeScript会报错
const badChain: ModuleChain<string, string> = [moduleA, moduleC];

方案二:解决类实现的问题

针对你提到的类实现的两个痛点,我们可以拆分基础链和链式结构,并通过辅助函数自动推断中间类型:

1. 定义链结构类

// 基础链:仅包含单个模块,无后续节点
class SingleModuleChain<TInput, TOutput> {
  constructor(public module: Module<TInput, TOutput>) {}

  // 执行链式调用
  passThrough(input: TInput): TOutput {
    return this.module.passThrough(input);
  }
}

// 链式节点:包含头部模块和后续链
class LinkedModuleChain<TInput, TIntermediate, TOutput> {
  constructor(
    public head: Module<TInput, TIntermediate>,
    public tail: SingleModuleChain<TIntermediate, TOutput> | LinkedModuleChain<TIntermediate, any, TOutput>
  ) {}

  passThrough(input: TInput): TOutput {
    const intermediate = this.head.passThrough(input);
    return this.tail.passThrough(intermediate);
  }
}

// 统一对外的类型别名
type ModuleChainClass<TInput, TOutput> = 
  | SingleModuleChain<TInput, TOutput>
  | LinkedModuleChain<TInput, any, TOutput>;

2. 辅助函数简化创建

通过函数重载和递归调用,自动推断中间类型,无需手动指定:

// 函数重载:支持1个、2个、3个...模块的链式创建
function chain<TInput, TOutput>(module: Module<TInput, TOutput>): SingleModuleChain<TInput, TOutput>;
function chain<TInput, TIntermediate, TOutput>(
  first: Module<TInput, TIntermediate>,
  second: Module<TIntermediate, TOutput>
): LinkedModuleChain<TInput, TIntermediate, TOutput>;
function chain<TInput, T1, T2, TOutput>(
  first: Module<TInput, T1>,
  second: Module<T1, T2>,
  third: Module<T2, TOutput>
): LinkedModuleChain<TInput, T1, TOutput>;
// 扩展更多参数的重载(按需添加)
function chain(...modules: any[]): any {
  if (modules.length === 1) {
    return new SingleModuleChain(modules[0]);
  }
  const head = modules[0];
  const tail = chain(...modules.slice(1));
  return new LinkedModuleChain(head, tail);
}

使用示例

// 自动推断类型,无需手动指定泛型
const chainClass1 = chain(moduleA, moduleB, moduleC, moduleD);
// 调用链式处理
const result = chainClass1.passThrough("123"); // 类型为string

// 非法情况:传入类型不匹配的模块,TypeScript会直接报错
const badChainClass = chain(moduleA, moduleC);

内容的提问来源于stack exchange,提问作者Tim Leach

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 12:55:13