为Columns数组中的rowData和cellData推导TypeScript类型
TypeScript泛型列类型优化:自动推导rowData类型
我需要为以下JavaScript数据结构创建TypeScript类型:
const columns = [ { dataKey: 'field1', label: 'Field 1', render: ({ rowData, cellData }) => { return null; }, }, { label: 'Actions', render: ({ rowData }) => { return null; }, }, ]
核心需求:通过泛型为columns标注类型,自动推导每个列对象的rowData和cellData类型——当列对象不存在dataKey时,cellData类型应为undefined。
目前我的实现存在问题:指定dataKey时,rowData和cellData的类型能正确推导;但未指定dataKey时,rowData会被推断为any类型,虽然TypeScript会对错误取值报错,但无法正确识别rowData的实际类型。
现有实现代码:
type ColumnDef<T, U> = { label: string; render: (args: { rowData: T; cellData: U }) => null; }; type ColumnWithoutKey<T> = ColumnDef<T, undefined>; type ColumnWithKey<T> = { [K in keyof T]: T[K] extends infer TK ? { dataKey: K } & ColumnDef<T, TK> : never; }[keyof T]; type HasDataKey = { dataKey: string; }; type Column<T, U = any> = U extends HasDataKey ? ColumnWithKey<T> : ColumnWithoutKey<T>; type Columns<T> = Array<Column<T>>; type Data = { field1: string; field2: number; // only work if I have two or more fields }; const columns: Columns<Data> = [ { dataKey: 'field1', // 可以自动补全dataKey的可选值 label: 'Field 1', // rowData类型为Data,cellData类型为string,均正确 render: ({ rowData, cellData }) => { return null; }, }, { label: 'Actions', // rowData和cellData都被推断为any类型 render: ({ rowData, cellData }) => { return null; }, }, { label: 'Actions', // 会报错field3不存在,但改为field2后,类型仍显示为any render: ({ rowData: { field3 } }) => { return null; }, }, ];
解决方案
问题根源在于原Column<T, U = any>的条件判断逻辑依赖默认参数any,导致类型推断歧义。我们可以直接将Column<T>定义为带dataKey的列类型与不带dataKey的列类型的联合类型,避免条件分支的歧义:
优化后的类型定义:
type ColumnDef<T, U> = { label: string; render: (args: { rowData: T; cellData: U }) => null; }; // 不带dataKey的列,cellData固定为undefined type ColumnWithoutKey<T> = ColumnDef<T, undefined>; // 带dataKey的列,dataKey对应T的键,cellData对应该键的类型 type ColumnWithKey<T> = { [K in keyof T]: { dataKey: K } & ColumnDef<T, T[K]>; }[keyof T]; // 直接合并两种列类型为联合类型 type Column<T> = ColumnWithKey<T> | ColumnWithoutKey<T>; type Columns<T> = Column<T>[]; type Data = { field1: string; field2: number; }; const columns: Columns<Data> = [ { dataKey: 'field1', label: 'Field 1', render: ({ rowData, cellData }) => { // rowData: Data, cellData: string return null; }, }, { label: 'Actions', render: ({ rowData, cellData }) => { // rowData: Data, cellData: undefined return null; }, }, { label: 'Actions', render: ({ rowData: { field2 } }) => { // rowData: Data,field2类型正确识别为number return null; }, }, ];
优化说明
- 移除了原有的
HasDataKey条件判断和默认参数U = any,消除类型推断的歧义 - 直接通过联合类型定义
Column<T>,TypeScript会自动区分两种列结构,同时保证rowData始终绑定为泛型T的类型 - 无论是否携带
dataKey,rowData都会正确推导为传入的泛型类型,cellData在无dataKey时为undefined,有dataKey时为对应字段的类型
内容的提问来源于stack exchange,提问作者Gustavo
相关产品推荐
相关产品推荐

