如何为indexById函数实现TypeScript类型安全的输出?
实现带类型安全的
indexById函数 需求概述
需要实现一个indexById函数,接收由带唯一id属性的对象组成的数组作为参数,返回一个以对象id为键、对应原对象为值的映射对象。核心要求是TypeScript能精确推断返回对象中每个键对应的类型,比如访问output['3'].value.someProp时,TS能识别出这是number类型。
解决方案
类型定义与函数实现
利用TypeScript的泛型和条件类型,我们可以让TS精准推断输入数组中每个元素的类型,并映射到输出对象的对应键上:
type IndexedById<T extends readonly { id: string; value: unknown }[]> = { [P in T[number]['id']]: Extract<T[number], { id: P }> }; function indexById<T extends readonly { id: string; value: unknown }[]>( arr: T ): IndexedById<T> { return arr.reduce((acc, item) => { acc[item.id as keyof typeof acc] = item; return acc; }, {} as IndexedById<T>); }
使用示例
当传入带const断言的数组(或直接传入字面量数组)时,TS会完全保留每个元素的类型信息:
const input = [ { id: '1', value: 'abc' }, { id: '2', value: 123 }, { id: '3', value: { someProp: 3 } } ] as const; const output = indexById(input); // TS能正确识别类型: output['1'].value; // 类型为 "abc" output['2'].value; // 类型为 123 output['3'].value.someProp; // 类型为 number // 若访问不存在的id,TS会报错: output['4']; // 类型错误:类型“"4"”不存在于类型“IndexedById<...>”上
关键说明
- 泛型约束:
T extends readonly { id: string; value: unknown }[]确保输入数组的元素都包含id和value属性,readonly兼容const断言的数组。 - 映射类型:
[P in T[number]['id']]遍历数组中所有元素的id作为键。 - 条件提取:
Extract<T[number], { id: P }>提取出数组中id等于P的元素类型,保证每个键对应的值类型完全匹配原数组中的对象。 - 类型断言:函数内部的
{} as IndexedById<T>是为了让TS认可reduce的返回值类型,避免不必要的类型报错。
内容的提问来源于stack exchange,提问作者Gaurav Mukherjee
相关产品推荐
相关产品推荐

