TypeScript泛型函数自定义返回类型的实现疑问
解决TypeScript泛型函数提取对象属性的类型化问题
你的问题核心是要给getFoodProperties函数的返回值和内部对象obj指定正确的泛型类型,替代any来实现类型安全。可以直接利用TypeScript内置的Pick工具类型来解决这个问题,它专门用来从一个类型中选取指定键对应的属性集合。
改造后的完整代码
// 补充定义IFoods类型 interface IFoods { name: string; colour: string; weight: number; } function getFoodProperties<T, K extends keyof T>(foods: T[], keys: K[]): Pick<T, K>[] { return foods.map((food) => { // 用Pick<T, K>断言空对象,告诉TS这个对象最终会包含指定属性 let obj = {} as Pick<T, K>; keys.forEach((key) => { obj[key] = food[key]; }); return obj; }); } const foods: IFoods[] = [ { name: "Beef", colour: "Red", weight: 8 }, { name: "Chips", colour: "Yellow", weight: 1 }, { name: "Lettuce", colour: "Green", weight: 9 }, ]; // 返回值类型会被正确推导为Pick<IFoods, "name" | "colour">[],即{name: string; colour: string}[] const result = getFoodProperties(foods, ["name", "colour"]);
关键改动说明
- 返回值类型替换:把
any[]改成Pick<T, K>[],Pick<T, K>表示从类型T中选取所有K包含的键对应的属性,组成新的类型,完全匹配提取指定属性的逻辑。 - 内部obj类型处理:将
obj的类型从any改为Pick<T, K>,但因为初始是空对象{},TypeScript无法自动推导它会包含K对应的属性,所以用as Pick<T, K>做类型断言,避免Type 'K' cannot be used to index type '{}'的报错。 - 类型推导验证:调用函数时,传入
["name", "colour"],TypeScript会自动将K推导为"name" | "colour",返回的result类型会被准确推断为包含name和colour属性的对象数组,后续使用时能获得完整的类型提示和校验。
可选优化:用reduce替代forEach
如果不想用类型断言,也可以用reduce构建对象,让TypeScript自动推导类型:
function getFoodProperties<T, K extends keyof T>(foods: T[], keys: K[]): Pick<T, K>[] { return foods.map((food) => { return keys.reduce((acc, key) => { acc[key] = food[key]; return acc; }, {} as Pick<T, K>); }); }
内容的提问来源于stack exchange,提问作者JamesG
相关产品推荐
相关产品推荐

