提效保质:使用React泛型组件

在一次功能上线中,由于接口字段变动没有及时同步,导致出现问题。如何避免?

强类型的Table组件

动机与目的

ant design 的 Table 组件中,column 的 dataIndex 属性是列数据在数据项中对应的 key,为了支持 a.b.c、a[0].b.c[1] 这样的嵌套写法,所以是string类型的,这也是bug的根源:无法与数据的字段“绑定”,当接口变动时,IDE不会报错,而是导致运行时错误。同时render函数中的value参数给出any,也不能利用接口中已有的类型信息。

因此对Table组件进行了一层“包装”,实现为一个泛型组件,传入字段类型后可以约束columns的写法。内部进行一个简单的翻译,旨在完全兼容原本的Table组件(以及​ColumnProps​、​TableProps​)

实现思路

核心部分:给columns一个泛型类型,自动推断出需要填写的字段及其类型,并且可以让render中的value提示对应的type

新的column definition直接省去了dataIndex,用Col的键名来直接获得

interface Col<K extends keyof T, T> extends Base<T>{
    render?: (value: T[K], record: T, index: number) => React.ReactNode;
    ... // other ColumnProps
}

export type Cols<T> = {
    [K in keyof T]?: Col<K, T>;
};

对于需要自定义的column,单独书写,并且可以指定renderOrder

这是一个wrapper,​genColumns​函数用来将我们的columns转换成ant design的​ColumnProps​,rowKey也是强类型的,确保设置了合适的rowKey

Usage

目前存在的问题

  • rowSelection 中,selectedRowKeys 没有类型提示

  • column 不支持嵌套,即 children 中的 column 没有类型提示

  • 原本的 dataIndex:是列数据在数据项中对应的 key,支持 a.b.c、a[0].b.c[1] 的嵌套写法,我们的强类型 Table 不支持

  • 有一定重写成本

进一步思考

动手做了个小实验,发现 ​Ant Design​ 中有三个涉及到数据的组件已经支持了泛型:

Select

select.d.ts

业务:课次多选器

List

list.d.ts

Usage

Table

table.d.ts

摘自:https://ant.design/components/table-cn/arrow-up-right

暂时没有发现别的组件支持泛型,也的确只有数据展示型的组件需要这样设计。

在生产开发中提取通用的组件时,可以考虑设计为泛型组件:在更具通用性的同时避免误用,借助typescript为写代码提高效率和质量。

最后更新于