如何通过ColDef的field属性推断valueFormatter的TypeScript类型?
基于ColDef实现字段关联的类型推断
问题背景
假设我们有如下业务类型:
type Order = { id: string, product: string, quantity: number, timestamp: Date, }
在Angular项目中使用AG Grid时,默认的GridOptions<Order>无法为valueFormatter提供严格的类型推断:
const gridOptions: GridOptions<Order> = { columnDefs: [ { field: 'id' }, { field: 'product' }, { field: 'quantity', // params被推断为ValueFormatterParams<Order, any>,而非期望的ValueFormatterParams<Order, number> valueFormatter: (params) => params.value.toLocaleString(), }, ], };
更严重的是,当前类型系统无法阻止错误的类型定义:
{ field: 'timestamp', // 此处手动指定params类型为number,但实际运行时value是Date,类型不匹配却不会报错 valueFormatter: (params: ValueFormatterParams<Order, number>) => `${params.value + 1}`, }
我们需要让TypeScript根据field字段的值,自动推断valueFormatter的参数类型,从而在类型不匹配时触发错误。
解决方案
核心思路是利用映射类型生成每个字段对应的列定义联合类型,让TypeScript自动关联field和valueFormatter的类型:
// 定义单个严格列类型,绑定字段与valueFormatter参数类型 type StrictColDef<TData, TProp extends keyof TData> = ColDef<TData> & { field: TProp; valueFormatter?: (params: ValueFormatterParams<TData, TData[TProp]>) => string; }; // 生成所有字段对应的列定义联合类型 type StrictColDefUnion<TData> = { [K in keyof TData]: StrictColDef<TData, K> }[keyof TData]; // 替换GridOptions中的columnDefs类型 type StrictGridOptions<TData> = Omit<GridOptions<TData>, 'columnDefs'> & { columnDefs: StrictColDefUnion<TData>[]; };
效果验证
使用StrictGridOptions<Order>后,TypeScript会自动完成类型推断并拦截错误:
const gridOptions: StrictGridOptions<Order> = { columnDefs: [ { field: 'id' }, { field: 'product' }, { field: 'quantity', // params自动推断为ValueFormatterParams<Order, number>,类型正确 valueFormatter: (params) => params.value.toLocaleString(), }, { field: 'timestamp', // 触发类型错误:params.value是Date类型,无法执行+1操作 valueFormatter: (params) => `${params.value + 1}`, }, ], };
原理说明
StrictColDef<TData, TProp>通过泛型参数TProp绑定field字段和valueFormatter的参数类型,确保valueFormatter的params.value类型与field对应的数据类型一致。StrictColDefUnion<TData>通过映射遍历TData的所有键,生成每个键对应的StrictColDef类型,再取这些类型的联合。当TypeScript解析columnDefs数组时,会自动将每个列项匹配到对应的StrictColDef类型,从而完成精确的类型推断。
内容的提问来源于stack exchange,提问作者Ilan Segal
相关产品推荐
相关产品推荐

