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

如何使用TypeScript实现类型化元编程?解决键值对象生成函数的精确类型推导问题

实现精确类型推导的TypeScript元编程方案

我来帮你搞定这两个模式的精确类型推导问题,咱们一步步优化代码,让TypeScript能完美追踪每个键值对的类型。

一、工厂链式模式的优化

你原来的工厂模式里,subModules用了Record<string, unknown>,这直接丢失了所有具体类型信息,导致build()返回的结果全是unknown类型。咱们改成用泛型来动态跟踪已添加的键值对类型就行:

const maker = <T extends object = {}>(subModules: T = {} as T) => { 
  const add = <Name extends string, V>(key: Name, value: V) => { 
    // 合并现有类型与新键值对的类型,确保类型精确合并
    const newSubModules = { ...subModules, [key]: value } as T & { [K in Name]: V };
    return maker(newSubModules);
  };
  const build = () => subModules;
  return { add, build };
};

// 调用示例,现在类型完全精确推导
const m2 = maker() 
  .add('fn', ({a, b}: { a: number, b: number }) => a + b) 
  .add('foo', 1) 
  .add('bar', 'aaaa') 
  .build();

// 此时 m2 的类型是:
// {
//   fn: (args: { a: number; b: number; }) => number;
//   foo: number;
//   bar: string;
// }

关键改进点:

  • 给maker函数添加泛型T,默认是空对象,用来跟踪当前已收集的键值对类型
  • 每次调用add时,将新键值对的类型与T合并,生成新的泛型参数传递给下一个maker实例
  • 这样TypeScript就能逐步累积类型信息,最终build()返回的对象类型完全匹配你添加的所有键值对

二、流水线模式的优化

你原来的流水线模式里,类型映射{ [P in T[number]['key']]: T[number]['value'] }会把所有值的类型合并成联合类型,没法区分每个键对应的具体值类型。咱们用Extract工具类型来精准匹配每个键对应的元素值:

// 定义结果类型:从数组元素中提取对应key的value类型
type MetaMakerResult<T extends { key: string; value: unknown }[]> = {
  [K in T[number]['key']]: Extract<T[number], { key: K }>['value'];
};

const metaMaker = <T extends { key: string; value: unknown }[]>(...subModules: [...T]) => {
  return subModules.reduce((acc, curr) => {
    return { ...acc, [curr.key]: curr.value };
  }, {}) as MetaMakerResult<T>;
};

// 调用示例,类型精确推导
const m = metaMaker( 
  {key: 'fn', value: ({a, b}: { a: number, b: number }) => a + b}, 
  {key: 'foo', value: 1}, 
  {key: 'bar', value: 'aaaa'}, 
);

// 此时 m 的类型是:
// {
//   fn: (args: { a: number; b: number; }) => number;
//   foo: number;
//   bar: string;
// }

关键改进点:

  • 自定义MetaMakerResult类型,用Extract<T[number], { key: K }>找到数组中key为K的元素,然后取它的value类型
  • 这样每个键对应的类型都是其自身传入值的精确类型,不会和其他值的类型混淆
  • 使用[...T]元组类型确保TypeScript能正确推导数组中每个元素的具体类型,而不是合并成宽泛的数组类型

现在这两个方案都能实现你想要的精确类型推导,不管是链式添加还是一次性传入多组键值对,TypeScript都会完美追踪每个值的类型,满足你的类型化元编程需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 14:19:13