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

如何定义参数为前序回调返回值合并类型的可变参回调函数

实现类型安全的specialFunction:链式回调的合并参数约束

需求是实现一个specialFunction,可以接收任意数量的回调函数,每个回调的唯一参数必须是之前所有回调返回值的合并类型,同时不能硬编码参数数量。期望的调用行为如下:

// 合法调用:无类型错误
specialFunction(
  () => ({a: 1}), 
  (arg) => {
    console.log(arg.a)
    return { b: 2}
  },
  (arg) => {
    console.log(arg.a)
    console.log(arg.b)
  }
)

// 非法调用:触发TypeScript错误
specialFunction(
  () => ({a: 1}), 
  (arg) => {
    console.log(arg.b) // 错误:arg上不存在b属性
    return { b: 2}
  },
  (arg) => {
    console.log(arg.a)
    console.log(arg.c) // 错误:arg上不存在c属性
  }
)

之前尝试的代码无法正确推导第三个回调的参数类型,下面是可行的解决方案:

完整实现代码

// 合并两个对象类型,后一个类型的键会覆盖前一个
type Merge<A, B> = Omit<A, keyof B> & B;

// 递归构建链式回调的类型数组
type ChainCallbacks<
  T extends unknown[] = [],
  Acc = {}
> = T extends [infer First, ...infer Rest]
  ? First extends (arg: infer Arg) => infer Ret
    ? Arg extends Acc
      ? [(arg: Acc) => Ret, ...ChainCallbacks<Rest, Merge<Acc, Ret>>]
      : never
    : never
  : [];

const specialFunction = <T extends unknown[]>(
  ...callbacks: ChainCallbacks<T>
) => {
  let mergedResult: Record<string, unknown> = {};
  for (const cb of callbacks) {
    const result = cb(mergedResult as any);
    if (result) {
      mergedResult = {...mergedResult, ...result};
    }
  }
  return mergedResult;
};

代码解释

  1. Merge类型:用于合并两个对象类型,如果存在重复键,后面的类型会覆盖前面的,保证最新的返回值属性优先。
  2. ChainCallbacks类型:递归遍历回调数组,为每个回调指定参数类型为之前所有返回值的合并结果(Acc累加器),同时将当前回调的返回值合并到累加器中,传递给下一个回调。
  3. specialFunction函数:接收符合ChainCallbacks类型约束的回调数组,执行时维护一个合并结果对象,依次调用每个回调并更新合并结果。

测试验证

// 合法调用:完全符合类型约束
specialFunction(
  () => ({a: 2}),
  ({a}) => ({b: a + 1}), // arg类型为{a: number}
  ({a, b}) => ({c: a + b}) // arg类型为{a: number, b: number}
);

// 非法调用:触发类型错误
specialFunction(
  () => ({a: 2}),
  ({b}) => ({c: 3}), // 错误:arg上不存在b属性
  ({d}) => ({e: 4})  // 错误:arg上不存在d属性
);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 13:40:44