如何定义带Key属性的TypeScript泛型接口,且该Key可用于接口内另一个属性的函数中?
如何定义带Key属性的TypeScript泛型接口,且该Key可用于接口内另一个属性的函数中?
看起来你是想让表格列的配置严格绑定到数据源的类型,同时让渲染函数能自动识别列key对应的属性类型对吧?我之前做React表格组件的时候也纠结过这个问题,其实用TypeScript的泛型约束+索引类型就能完美解决,给你一步步拆解:
首先先把你提到的代码补全并修正,原来的写法大概率是因为没给Column接口加精准的泛型约束,才导致key和render函数的类型没法关联起来:
// 示例数据源类型 interface SomeObject { id: number name?: string age: number } // 你之前的Column可能是这样,render的value只能用any,类型完全不严谨 // interface Column<T> { // key: string // render: (value: any) => React.ReactNode // title: string // }
接下来是正确的定义方式,我们给Column接口新增一个泛型参数K,让它严格约束为T的属性键:
// 定义Column接口,K是T的属性键,作为第二个泛型参数 interface Column<T, K extends keyof T = keyof T> { // key必须是T的其中一个属性名,彻底杜绝拼写错误 key: K // render的value自动对应T[K]类型,再也不用写any或者手动断言! render: (value: T[K], row?: T) => React.ReactNode // 列标题,必填属性 title: string // 你还可以加其他列配置,比如宽度、对齐方式等 width?: string } // DataTableProps保持原泛型T,columns是Column<T>的数组即可 export interface DataTableProps<T> { columns: Column<T>[] data: T[] }
现在看看实际使用的效果,TypeScript会自动帮你做类型推断,完全不用手动干预:
// 配置列的时候,每个列的key会自动被约束为SomeObject的属性 const tableColumns: Column<SomeObject>[] = [ { key: 'id', title: '用户ID', render: (value) => { // 这里value会自动推断为number类型,能直接调用number的方法 return <span className="font-bold">{value}</span> }, width: '80px' }, { key: 'name', title: '用户姓名', render: (value, row) => { // value自动推断为string | undefined,所以可以用??处理空值 // row参数是整行数据,类型是SomeObject,能直接用row.age等其他属性 return <span>{value ?? `用户${row.id}`}</span> } } ] // 数据源也严格对应SomeObject类型 const tableData: SomeObject[] = [ { id: 1, name: '张三', age: 28 }, { id: 2, age: 32 } // name是可选属性,所以可以不填 ] // 使用DataTable组件时,类型完全匹配,不会出现key写错或者render类型不匹配的问题 // <DataTable data={tableData} columns={tableColumns} />
这里还有个小细节:给K加了= keyof T的默认值,这样你在使用Column的时候不用手动指定K,TS会根据你写的key自动推断对应的类型。如果某列需要更严格的约束(比如强制key只能是'id'),也可以手动指定Column<SomeObject, 'id'>,不过一般默认值就够用了。
另外,如果你希望整个columns数组的key不能重复,还可以用泛型元组做更严格的约束,但那是进阶用法了,上面的写法已经能解决大部分日常需求啦~
内容来源于stack exchange
相关产品推荐
相关产品推荐

