如何在TypeScript中实现数组转对象的泛型工具函数?
报错翻译
你第二次遇到的TS报错完整翻译如下:
类型“T[U]”不满足约束“string | number | symbol”。
类型“T[keyof T]”不可赋值给类型“string | number | symbol”。
类型“T[string] | T[number] | T[symbol]”不可赋值给类型“string | number | symbol”。
类型“T[string]”不可赋值给类型“string | number | symbol”。
类型“T[string]”不可赋值给类型“symbol”。
类型“T[keyof T]”不可赋值给类型“symbol”。
类型“T[U]”不可赋值给类型“symbol”。
类型“T[keyof T]”不可赋值给类型“symbol”。
类型“T[string] | T[number] | T[symbol]”不可赋值给类型“symbol”。
类型“T[string]”不可赋值给类型“symbol”。ts(2344)
错误原因
两次报错的核心问题可以分为两点:
- 第一次你写的
Record<U, V>对泛型参数理解错误:Record<键类型, 值类型>的第一个参数是最终返回的对象的键的类型,第二个是值的类型。你传入的U是数组元素的键名的类型(比如示例里的'name'),但你实际用作返回对象键的是ele[key]也就是键对应的值(比如示例里的'isaac',类型为T[U]),同理值的类型应该是T[V]而不是V,这是第一次报错的根源。 - 第二次报错是因为TS规定对象的键只能是
string | number | symbol三种类型(TS内置别名是PropertyKey),你只约束了T extends object,没有限定T[U]属于合法的对象键类型,所以TS会抛出类型不满足约束的报错。
正确实现
最简单的修复方案是直接在泛型约束里限定你用来做键的属性值的类型:
const convertListToMap = < // 约束T中U对应的属性值一定是合法的对象键类型 T extends Record<U, PropertyKey>, U extends keyof T, V extends keyof T >( list: T[], key: U, secondKey: V ) => { const map = {} as Record<T[U], T[V]>; for (const ele of list) { map[ele[key]] = ele[secondKey]; } return map; };
类型推导验证
调用你给出的示例代码,类型可以正常推导:
// 返回值类型自动推导为 Record<string, number> convertListToMap([{name: 'isaac', age: 17}, {name: 'john', age: 20}], 'name', 'age'); // 返回值类型自动推导为 Record<string, string> convertListToMap([{race: 'chinese', language: 'mandarin'}, {race: 'malay', language: 'melayu'}], 'race', 'language');
内容的提问来源于stack exchange,提问作者Isaac
相关产品推荐
相关产品推荐

