TypeScript 4中如何接收泛型元组参数并返回正确泛型类型?
解决TypeScript中保留元组元素类型的merge函数问题
你的问题核心在于原代码的泛型约束限制了所有STORE实例的泛型参数必须是同一个类型U,这就导致当传入不同类型的data时,TypeScript只能推断出它们的公共类型(比如unknown或者联合类型),无法保留元组中每个元素的具体类型信息。
下面是修正后的实现方案,能够准确保留输入元组的类型,返回对应的STORE<元组类型>:
interface STORE<T> { data: T; } const merge = <T extends readonly STORE<any>[]>( values: T ): STORE<{ [K in keyof T]: T[K] extends STORE<infer V> ? V : never }> => { // 断言初始值类型为目标STORE类型,帮助TypeScript正确推断 return values.reduce( (acc, item) => ({ data: [...acc.data, item.data] }), { data: [] } as STORE<{ [K in keyof T]: T[K] extends STORE<infer V> ? V : never }> ); };
关键改动说明:
- 移除单一泛型约束:不再强制所有
STORE的泛型参数为同一个U,而是让T直接表示输入的STORE元组类型,保留每个元素的独立类型信息。 - 映射类型提取元组元素类型:通过
{ [K in keyof T]: T[K] extends STORE<infer V> ? V : never }遍历元组的每个索引,提取对应STORE实例中的data类型,组成新的元组类型。 - 初始值类型断言:由于
reduce的初始值{ data: [] }默认会被推断为STORE<never[]>,需要用类型断言告诉TypeScript它最终会成为我们期望的元组类型。
使用示例:
调用时需要添加as const来让TypeScript将数组推断为元组(否则会被当成普通数组,类型退化为联合类型数组):
const result = merge([{ data: 'test' }, { data: 2 }] as const); // result的类型为STORE<['test', 2]>,完全符合你的期望
如果不需要只读元组,也可以手动指定元组类型:
const input: [STORE<string>, STORE<number>] = [{ data: 'test' }, { data: 2 }]; const result = merge(input); // result的类型同样是STORE<['test', 2]>
内容的提问来源于stack exchange,提问作者ZNackasha
相关产品推荐
相关产品推荐

