如何使用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
相关产品推荐
相关产品推荐

