TypeScript如何根据接口某属性取值动态设置另一属性的类型
这个需求完全可以实现,不需要引入泛型,也不需要你手动判断类型,使用TypeScript的**可辨识联合类型(Discriminated Union)**就能完美满足要求,这就是你要找的关键词。
改造后的类型定义
export type DataGridColumnType = 'currency' | 'date' | 'number' | 'text'; interface CurrencyColumnOptions { symbol: string; } interface DateColumnOptions { format: string; } interface NumberColumnOptions { decimalPoint: string; thousandSeparator: string; } // 空对象定义,避免额外非法属性 type TextColumnOptions = Record<string, never>; // 定义每种列类型对应的具体结构 interface CurrencyDataGridColumn { field: string; label: string; title: string; type: 'currency'; columnOptions?: CurrencyColumnOptions; } interface DateDataGridColumn { field: string; label: string; title: string; type: 'date'; columnOptions?: DateColumnOptions; } interface NumberDataGridColumn { field: string; label: string; title: string; type: 'number'; columnOptions?: NumberColumnOptions; } interface TextDataGridColumn { field: string; label: string; title: string; type?: 'text'; columnOptions?: TextColumnOptions; } // 组合成联合类型,直接替代原来的DataGridColumn接口 export type DataGridColumn = | CurrencyDataGridColumn | DateDataGridColumn | NumberDataGridColumn | TextDataGridColumn; export interface DataGrid { columns: DataGridColumn[]; rows: Record<string, unknown>[]; }
效果验证
定义完成后原有使用逻辑完全不需要修改,TS会自动做类型匹配校验:
// 正常通过校验 const column: DataGridColumn = { field: 'id', label: 'ID', title: 'ID', type: 'date', columnOptions: { format: 'YYYY-mm-dd', // 匹配date类型的合法属性 }, }; // 会触发TS类型错误:date类型的columnOptions不允许存在symbol属性 const wrongColumn: DataGridColumn = { field: 'price', label: '价格', title: '价格', type: 'date', columnOptions: { symbol: '¥' } }
方案优势
- 完全不需要引入泛型,上层使用表格组件的方式和原来完全一致,不会增加任何使用复杂度
- 就算表格组件存在深层嵌套结构,可辨识联合类型的自动推断也能正常生效,不需要额外的类型注解
- 后续新增列类型时,只需要新增对应的列接口,再加入
DataGridColumn联合类型即可,维护成本很低
内容的提问来源于stack exchange,提问作者Jonathan Pellerin
相关产品推荐
相关产品推荐

