TypeScript泛型函数如何自动推导类型,无需显式传入?
解决TypeScript分组计数函数的泛型自动推导问题
问题背景
需要实现一个按指定键对数组元素分组计数的函数,当前代码功能正常,但调用时必须显式指定泛型类型,无法通过传入参数自动推导泛型,导致使用不便。
问题原因
原函数的泛型参数顺序和约束逻辑存在问题:
- 泛型参数
FilterOptions被放在最后,而它实际上是T[PropName]的类型,TypeScript无法从已推导的T和PropName反向推导FilterOptions; T的约束写法<T extends { [R in PropName]: FilterOptions }>逻辑倒置,应该是从T和PropName确定值类型,而非先定义值类型再约束T。
解决方案
调整泛型参数结构,直接从T和PropName推导目标属性的值类型,无需单独定义FilterOptions泛型参数。具体修改如下:
修改后的函数代码
export const aggregateProp = <T, PropName extends keyof T>( evaluations: T[], propName: PropName ) => { type FilterOptions = T[PropName]; const totalsByResult = evaluations.reduce((acc, { [propName]: result }) => { acc.set(result, (acc.get(result) ?? 0) + 1); return acc; }, new Map<FilterOptions | 'ALL', number>()); totalsByResult.set('ALL', evaluations.length); return totalsByResult; };
调用验证
使用原有的Evaluation接口和测试数组,现在可以直接隐式调用,TypeScript会自动推导泛型类型:
interface Evaluation { propA: string; result: FilterOptions; probC: boolean; } type FilterOptions = 'FAILED' | 'SUCCESS' | 'SKIPPED' | 'ALL'; const evaluations: Evaluation[] = [ { propA: 'a', result: 'FAILED', probC: true }, { propA: 'b', result: 'FAILED', probC: false }, { propA: 'c', result: 'SUCCESS', probC: true }, { propA: 'd', result: 'SKIPPED', probC: false }, { propA: 'e', result: 'SKIPPED', probC: true }, { propA: 'f', result: 'FAILED', probC: false }, ]; // 自动推导为 Map<FilterOptions | 'ALL', number> const implicit = aggregateProp(evaluations, 'result');
说明
- 通过
type FilterOptions = T[PropName]从已推导的T和PropName获取目标属性的类型,避免了单独定义泛型参数的麻烦; - 泛型参数简化为
<T, PropName extends keyof T>,TypeScript可以轻松从传入的数组和属性名参数自动推导这两个类型,进而确定FilterOptions的类型; - 返回的
Map类型明确为FilterOptions | 'ALL',既保留了原有的分组计数,也包含了总数量的'ALL'键。
内容的提问来源于stack exchange,提问作者derduher
相关产品推荐
相关产品推荐

