TypeScript获取自身类型key及表格列类型约束技术问询
问题
- 在TypeScript中,有没有办法获取自身类型的
keyof? - 能不能把表格
columns中的字段值作为valueFormatter的参数类型?比如传入id、firstname、lastname作为列时,让valueFormatter函数的参数只包含这些键对应的类型,目标是让columns中的字段决定valueFormatter的参数类型。相关代码示例如下:
import "./App.css"; interface TableColumn { name: string; // TODO: make this type same as type of the keys in one of the objects in rows valueFormatter?: (datacolumn: { id: number; firstname: string; lastname: string; }) => void; } interface TableProps { columns: TableColumn[]; rows: any[]; } const Table = ({ columns, rows }: TableProps) => { return ( <div> <div style={{ display: "flex" }}> {rows.map((row, index) => ( <div key={`row-${index}`} style={{ display: "inline-flex" }}> {columns.map((col) => ( <div key={col.name} style={{ padding: "1rem", border: "1px solid white" }} > {col.valueFormatter ? col.valueFormatter(row) : row[col.name]} </div> ))} </div> ))} </div> </div> ); }; function App() { const columns = [ { name: "id", valueFormatter: (row) => { return row.firstname + "some value"; }, }, { name: "firstname" }, { name: "lastname" }, ]; const rows = [{ id: 1, firstname: "John", lastname: "Doe" }]; return ( <div className="App"> <Table columns={columns} rows={rows} /> </div> ); } export default App;
回答
1. 获取自身类型的keyof
完全可以,具体分几种场景实现:
- 类内部获取自身键类型:用
keyof this直接指向当前类实例的所有键
class User { id: number; name: string; getValidKeys(): Array<keyof this> { return Object.keys(this) as Array<keyof this>; } }
- 接口/类型别名内部引用:直接使用
keyof 自身类型名
interface Product { id: number; price: number; allowedKeys: Array<keyof Product>; }
- 泛型函数中获取参数自身键类型:通过泛型
T推断参数类型,再取keyof T
function getObjectKeys<T>(obj: T): Array<keyof T> { return Object.keys(obj) as Array<keyof T>; }
2. 让columns字段约束valueFormatter的参数类型
核心是用泛型关联行数据类型与列配置,让列名必须匹配行数据的键,同时valueFormatter的参数严格对应行数据类型。修改后的代码如下:
import "./App.css"; // 泛型T代表单行数据的类型,约束列名必须是T的键 type TableColumn<T> = { name: keyof T; valueFormatter?: (row: T) => React.ReactNode; }; // 表格Props用泛型T关联列和行的类型 interface TableProps<T> { columns: TableColumn<T>[]; rows: T[]; } // 表格组件接收泛型T,确保行是对象类型 const Table = <T extends Record<string, unknown>>({ columns, rows }: TableProps<T>) => { return ( <div> <div style={{ display: "flex" }}> {rows.map((row, index) => ( <div key={`row-${index}`} style={{ display: "inline-flex" }}> {columns.map((col) => ( <div key={`${index}-${String(col.name)}`} style={{ padding: "1rem", border: "1px solid #ccc" }} > {col.valueFormatter ? col.valueFormatter(row) : row[col.name]} </div> ))} </div> ))} </div> </div> ); }; function App() { // 显式声明行数据类型,让列配置和行数据强关联 type RowType = { id: number; firstname: string; lastname: string; }; const columns: TableColumn<RowType>[] = [ { name: "id", valueFormatter: (row) => { // 此处row被严格约束为RowType,只能访问id、firstname、lastname return `${row.firstname} 的ID是 ${row.id}`; }, }, { name: "firstname" }, { name: "lastname" }, ]; const rows: RowType[] = [{ id: 1, firstname: "John", lastname: "Doe" }]; return ( <div className="App"> <Table<RowType> columns={columns} rows={rows} /> </div> ); } export default App;
关键改动说明:
- 给
TableColumn和TableProps添加泛型T,让列配置与行数据类型绑定 TableColumn的name字段被约束为keyof T,确保列名必须是行数据中存在的键valueFormatter的参数类型直接使用T,函数内部只能访问行数据的合法属性,避免类型错误- 显式声明
RowType后,TypeScript会自动校验列名和valueFormatter的参数使用,提供准确的类型提示
内容的提问来源于stack exchange,提问作者Arvid W
相关产品推荐
相关产品推荐

