如何实现带不同类型引用的Columns<T>泛型类型定义
实现类型安全的嵌套子网格列泛型定义
要解决这个类型安全问题,核心是通过双泛型约束让子网格列类型从子项返回值自动推断,同时解除子模型与当前行模型的绑定限制。以下是具体实现方案:
1. 基础类型定义
先明确核心类型的结构,通过辅助工具类型提取数组元素类型,再定义普通列和子网格列:
// 辅助工具类型:提取数组的元素类型 type ArrayElement<T> = T extends (infer U)[] ? U : never; // 普通列类型:绑定当前行的模型T type Column<T> = { key: keyof T; label: string; // 可扩展其他通用属性,如 width、sortable 等 }; // 子网格列类型:T为当前行模型,N为子网格行模型 type SubgridColumn<T, N> = Column<T> & { type: 'subgrid'; // 接收当前行数据,返回子模型数组 subgridItems: (row: T) => N[]; // 子列类型自动匹配子模型N的列定义 subgridColumns: Columns<N>; }; // 列定义联合类型:包含普通列和任意子网格列 type ColumnDefinition<T> = Column<T> | SubgridColumn<T, any>; // 最终的列数组类型 type Columns<T> = ColumnDefinition<T>[];
2. 使用示例
以下示例展示了如何定义跨模型的子网格列,子模型无需与当前行模型有属性关联:
// 示例模型1:当前行模型 interface User { id: number; name: string; email: string; } // 示例模型2:子网格模型(与User无直接属性绑定) interface UsageCountry { country: string; usageCount: number; } // 定义User的列数组,TypeScript自动推断子网格类型 const userColumns: Columns<User> = [ { key: 'id', label: '用户ID' }, { key: 'name', label: '用户名' }, { key: 'email', label: '邮箱及使用地区', type: 'subgrid', // 返回UsageCountry[],TypeScript自动推断N为UsageCountry subgridItems: (user) => { // 可根据当前行数据生成子项,也可返回任意模型数组 return [ { country: '中国', usageCount: 120 }, { country: '美国', usageCount: 80 } ]; }, // subgridColumns被自动约束为Columns<UsageCountry>,类型错误会直接报错 subgridColumns: [ { key: 'country', label: '国家/地区' }, { key: 'usageCount', label: '使用次数' } ] } ];
关键特性说明
- 自动类型推断:
subgridColumns的类型会从subgridItems的返回数组中自动提取元素类型,无需手动指定子模型泛型参数 - 类型安全:如果
subgridColumns中出现子模型不存在的key,TypeScript会立即抛出类型错误 - 无绑定限制:子模型可以是任意类型,不需要与当前行模型
T有任何属性关联
内容的提问来源于stack exchange,提问作者Andyally
相关产品推荐
相关产品推荐

