如何合并双泛型元组?TypeScript泛型元组合并实现疑问
TypeScript双泛型元组合并实现方案
我需要实现一个函数,合并包含两个泛型的元组,但不知道怎么写代码。单个泛型类型的情况我能处理,但双泛型场景卡壳了。
我的代码示例如下:
type Value<TFirst, TLast> = { first: TFirst, last: TLast, } function combine<TFirst extends unknown[], TLast extends unknown[]>(...values: any): Value<TFirst, TLast> { return undefined as any; } function makeValue<TFirst, TLast>() { return undefined as any; } const test: Value<[string, number], [never, string]> = combine( makeValue<string, never>(), makeValue<number, string>() );
我试过用...values: [...{ [K in keyof TFirst]: K extends keyof TLast ? Value<TFirst[K], TLast[K]> : never }]这种写法,但没法正常工作。
解决方案
要解决这个问题,核心是让TypeScript能从传入的Value实例中自动推导并合并first和last对应的元组类型,而非先声明泛型再约束参数。我们可以通过提取元组元素属性的方式实现:
- 定义类型工具,从
Value组成的元组中提取所有first属性,形成新元组; - 同理提取所有
last属性形成另一个元组; - 让
combine函数接收Value类型的可变参数,自动推导参数元组类型,再返回合并后的Value类型。
具体实现代码:
type Value<TFirst, TLast> = { first: TFirst, last: TLast, } // 从Value元组中提取所有first属性组成的元组 type ExtractFirst<T extends Value<any, any>[]> = { [K in keyof T]: T[K] extends Value<infer F, any> ? F : never } // 从Value元组中提取所有last属性组成的元组 type ExtractLast<T extends Value<any, any>[]> = { [K in keyof T]: T[K] extends Value<any, infer L> ? L : never } function combine<T extends Value<any, any>[]>(...values: T): Value<ExtractFirst<T>, ExtractLast<T>> { // 运行时合并逻辑 const first = values.map(v => v.first) as ExtractFirst<T>; const last = values.map(v => v.last) as ExtractLast<T>; return { first, last }; } function makeValue<TFirst, TLast>(): Value<TFirst, TLast> { return { first: undefined as TFirst, last: undefined as TLast }; } // 测试:类型自动推导符合预期 const test = combine( makeValue<string, never>(), makeValue<number, string>() ); // test的类型为 Value<[string, number], [never, string]>
原写法失效原因
你之前的写法试图用TFirst和TLast约束参数类型,但这两个泛型需要从参数中推导,而参数类型又依赖这两个泛型,形成了循环依赖,TypeScript无法完成正确的类型推导。新方案先让TypeScript推导参数的元组类型,再从中提取目标元组,彻底避免了循环依赖问题。
内容的提问来源于stack exchange,提问作者Michael Shcherbakov
相关产品推荐
相关产品推荐

