如何让TypeScript创建查找对象的泛型函数支持自定义键并保留类型检查
增强TypeScript查找函数的通用性
你可以通过扩展泛型参数并新增键名参数,实现支持指定任意合法键的通用查找函数,同时保留严格的类型检查。以下是修改后的实现:
通用版函数代码
function createLookup<K extends PropertyKey, T extends Record<K, PropertyKey>>( source: T[], key: K ) { return Object.fromEntries(source.map(el => [el[key], el])) as Record<T[K], T>; }
泛型参数说明
K extends PropertyKey:约束传入的键名必须是合法的对象键类型(string、number、symbol)。T extends Record<K, PropertyKey>:确保输入数组中的每个对象都包含指定的K键,且该键对应的值是可作为对象索引的合法类型(保证能成为查找对象的键)。- 返回类型
Record<T[K], T>:明确查找对象的键类型为原对象中K字段的类型,值类型为原对象类型,让TypeScript能精准推断返回值的结构。
使用示例
示例1:使用数字类型键id
const users = [ { id: 1, name: "Alice", age: 30 }, { id: 2, name: "Bob", age: 25 } ]; const userLookup = createLookup(users, "id"); // 类型推断结果:Record<number, { id: number; name: string; age: number }> console.log(userLookup[1]); // 输出:{ id: 1, name: "Alice", age: 30 }
示例2:使用字符串类型键slug
const posts = [ { slug: "typescript-guide", title: "TS入门指南" }, { slug: "react-best-practices", title: "React最佳实践" } ]; const postLookup = createLookup(posts, "slug"); // 类型推断结果:Record<string, { slug: string; title: string }> console.log(postLookup["typescript-guide"]); // 输出:{ slug: "typescript-guide", title: "TS入门指南" }
类型检查效果
函数会自动拦截不合法的输入:
- 当数组对象缺少指定键时:
const invalidItems = [{ name: "Test" }]; createLookup(invalidItems, "id"); // TypeScript报错:类型"{ name: string; }"不满足"Record<"id", PropertyKey>"约束 - 当指定键对应的值不是合法索引类型时:
const invalidValueItems = [{ id: { value: 1 } }]; createLookup(invalidValueItems, "id"); // TypeScript报错:类型"{ value: number; }"无法赋值给PropertyKey类型
内容的提问来源于stack exchange,提问作者KorbenDose
相关产品推荐
相关产品推荐

