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

如何让TypeScript函数正确接收链式修饰器数组并实现类型校验

链式函数修饰器的TypeScript类型校验实现

完全可行,通过TypeScript的泛型与条件类型,可以精准追踪链式修饰器的输入输出类型,确保只有合法的修饰器序列能通过类型校验,同时正确推断最终返回值的类型。

实现方案

首先定义两个辅助类型,用于串联函数链并推断最终结果类型:

// 递归校验修饰器链的合法性:每个后续函数的输入必须匹配前一个的输出
type ChainableModifiers<T extends any[]> = T extends [infer First, ...infer Rest]
  ? First extends (data: infer In) => infer Out
    ? Rest extends ChainableModifiers<Rest>
      ? Rest extends [(data: Out) => infer NextOut, ...infer RestRest]
        ? [(data: In) => Out, ...ChainableModifiers<[(data: Out) => NextOut, ...RestRest]>]
        : [(data: In) => Out]
      : never
    : never
  : [];

// 提取修饰器链最终的返回值类型
type ChainResult<T extends any[]> = T extends [...infer _, (data: infer In) => infer Out]
  ? Out
  : {};

然后修改func函数,添加严格的泛型约束:

const func = <T extends ChainableModifiers<T>>(modifiers: T): ChainResult<T> => {
  return modifiers.reduce((acc, modifier) => modifier(acc), {} as any);
};

测试验证

使用你提供的修饰器函数进行测试:

const addA = (data: {}) => {
  return { ...data, a: "test" };
};

const addB = (data: {}) => {
  return { ...data, b: "test" };
};

const updateA = (data: { a: string }) => {
  return { ...data, a: `${data.a} test` };
};

console.log(func([addA])); // ✅ 类型校验通过,返回类型为 { a: string }
console.log(func([addA, addB])); // ✅ 类型校验通过,返回类型为 { a: string, b: string }
console.log(func([addA, addB, updateA])); // ✅ 类型校验通过,updateA的输入匹配前序结果
console.log(func([updateA])); // ❌ 类型校验报错:初始值{}不符合updateA的输入要求(需要{a: string})

原理说明

  • ChainableModifiers 通过递归遍历修饰器数组,强制每个后续函数的输入类型与前一个函数的输出类型匹配,非法序列会直接触发类型错误。
  • ChainResult 自动提取最后一个修饰器的输出类型,让func的返回值类型完全符合链式调用后的实际数据结构。
  • 泛型约束T extends ChainableModifiers<T>确保只有合法的修饰器链能被传入func,从根源上避免运行时因数据结构不匹配导致的错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 04:57:24