You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript实现表格行列类型安全:列定义约束行结构

TypeScript实现表格行与列的类型安全约束

要让表格行数据严格匹配列定义的结构,同时支持行的额外属性、实现渲染函数的类型安全,核心是利用泛型将列的定义与行的类型强绑定,同时通过类型映射实现字段类型的对应。

1. 基础类型定义

先定义类型映射规则,将列的type字段转换为TypeScript原生类型,同时定义行的通用可选属性:

// 列类型到TS原生类型的映射
type ColumnTypeToTS<T extends "string" | "number" | "action"> = 
  T extends "string" ? string :
  T extends "number" ? number :
  T extends "action" ? never : never;

// 行的通用可选属性
interface TableRowProps {
  rowType?: "Basic" | "Master";
}

2. 带类型约束的列定义

将TableColumn改为泛型接口,让renderFunction的参数类型与列的type自动匹配:

// 单个列的泛型定义,T为列的类型
interface TableColumn<T extends "string" | "number" | "action"> {
  name: string;
  type: T;
  id: string;
  // renderFunction的参数类型自动匹配列的type对应的TS类型
  renderFunction?: (data: ColumnTypeToTS<T>) => string;
}

3. 表格Props的泛型绑定

定义泛型的PaginatedTableProps,让columns的类型直接决定rows的结构:

// 从列数组类型中提取行的schema类型
type ColumnsToRowSchema<Columns extends readonly TableColumn<any>[]> = {
  [K in Columns[number]["name"]]: ColumnTypeToTS<Extract<Columns[number], { name: K }>["type"]>;
};

// 表格Props的泛型定义,Columns为列数组的具体类型
interface PaginatedTableProps<Columns extends readonly TableColumn<any>[]> {
  rows: Array<TableRowProps & ColumnsToRowSchema<Columns>>;
  columns: Columns;
}

4. 使用示例与类型校验

现在使用时,TypeScript会自动根据columns的定义校验rows的结构,同时检查renderFunction的参数类型:

const props: PaginatedTableProps<[
  TableColumn<"string">,
  TableColumn<"number">,
  TableColumn<"string">
]> = {
  columns: [
    { name: "f", type: "string", id: "1" },
    { name: "count", type: "number", id: "2" },
    { name: "z", type: "string", id: "3", renderFunction: (s: string) => s } // 类型匹配,合法
    // 如果这里写renderFunction: (n: number) => n.toString(),会报错:参数类型不匹配
  ],
  rows: [
    { f: "foo", count: 12345, z: "bar" }, // 合法
    { f: "zig", count: 6789 }, // ❌ 错误:缺少必填字段z
    { f: "bar", count: "123", z: "far" }, // ❌ 错误:count应为number类型,实际是string
    { f: "bas", count: 123, z: "asdf", rowType: "Basic" }, // 合法,包含可选属性
    { f: "bas", count: 123, z: "asdf", rowType: "Expert" } // ❌ 错误:rowType只能是"Basic"或"Master"
  ]
};

5. 简化泛型写法(可选)

如果不想手动指定泛型参数,可以写一个辅助函数让TypeScript自动推导列的类型:

function createTableProps<Columns extends readonly TableColumn<any>[]>(props: PaginatedTableProps<Columns>) {
  return props;
}

// 使用时无需手动指定泛型,自动推导
const props = createTableProps({
  columns: [
    { name: "f", type: "string", id: "1" },
    { name: "count", type: "number", id: "2" },
    { name: "z", type: "string", id: "3", renderFunction: (s) => s } // s的类型自动推导为string
  ],
  rows: [
    { f: "foo", count: 12345, z: "bar" },
    // 错误行同样会被自动校验
  ]
});

关键说明

  • 泛型Columns捕获了列数组的具体类型,包括每个列的name和type,确保行数据的字段名和类型完全匹配。
  • ColumnsToRowSchema通过映射类型,将列数组转换为行的对象类型,实现了列定义到行结构的自动转换。
  • 列的renderFunction参数类型通过ColumnTypeToTS与列的type强绑定,避免了类型不匹配的问题。

内容的提问来源于stack exchange,提问作者Pascal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 19:07:08