如何让TypeScript泛型函数第二个泛型参数可选,无需手动指定?
问题描述
我有一组不相关的对象,需要编写一个泛型函数来获取它们的值。给定以下类型:
type Circle = { color: string, radius: number, } type Person = { name: string, age: number, }
我希望能这样调用泛型函数:
getData<Circle>('circle-id', ['radius']) // 返回类型 { radius: number }
但目前实现的方案需要传入两个泛型参数,使用体验很差:
getData<Circle, ['radius']>('circle-id', ['radius'])
当前的实现代码如下:
const getData = <Node, T extends Array<keyof Node>>( nodeId: string, attributes: T ): { [K in T[number]]: Node[K] } => { // ... }
请问如何优化该函数,避免手动指定第二个泛型参数?我知道柯里化可能可以解决,但我的场景要求getData返回可序列化对象。
解决方案
你可以通过调整泛型参数约束、利用TypeScript自动类型推导来优化,无需手动指定第二个泛型参数。核心思路是让第二个泛型参数代表目标类型的键联合类型,而非键数组类型,让TS从传入的参数自动推导具体值。
优化后的代码如下:
const getData = <Node, T extends keyof Node>( nodeId: string, attributes: readonly T[] ): Pick<Node, T> => { // 示例实现:替换为实际的数据源获取逻辑 const rawData = {} as Node; return attributes.reduce((result, key) => { result[key] = rawData[key]; return result; }, {} as Pick<Node, T>); };
调用示例
现在可以按照预期方式调用,TS会自动推导第二个泛型参数:
// 返回类型为 { radius: number } getData<Circle>('circle-id', ['radius']); // 返回类型为 { name: string; age: number } getData<Person>('person-id', ['name', 'age']);
关键说明
- 泛型参数调整:将
T的约束改为keyof Node,让T代表单个键或键的联合类型,TS能从数组参数自动推导T的具体值。 - 返回类型简化:使用TS内置的
Pick工具类型,直接从Node中选取指定属性集合,替代手动映射的类型定义,代码更简洁。 - readonly数组参数:用
readonly T[]作为参数类型,既兼容普通数组传入,又能避免TS将数组字面量类型拓宽为string[],确保类型推导准确。
内容的提问来源于stack exchange,提问作者macabeus
相关产品推荐
相关产品推荐

