React+Typescript开发表格时列内容含string和JSX的类型问题如何解决?
实现方案
核心问题
问题核心是将业务逻辑用的原始纯数据和渲染层用的JSX元素混合存储在同一个字段数组中,既不符合单一职责设计原则,也会触发TypeScript的类型校验报错,就算显式声明联合类型,后续做排序、筛选时也需要额外做类型判断,增加冗余逻辑。
推荐落地方案(优先选择)
1. 拆分数据层与渲染层,数据层仅存纯字符串
所有用于排序、筛选的原始数据统一存储纯字符串类型,完全不涉及任何JSX相关逻辑,先定义清晰的TS类型:
// 原始数据层类型,仅存储纯文本业务数据 interface TableRowRaw { col1: string[] col2: string[] expanded: string[] // 其余自定义列字段 } // 全局状态中仅存储原始数据和筛选状态 const [tableData, setTableData] = useState<TableRowRaw[]>([]) const [filterKeyword, setFilterKeyword] = useState<string>('')
2. 所有格式化、高亮逻辑放到渲染层封装
将JSX生成逻辑全部抽到渲染组件中,根据原始数据和当前筛选状态动态生成渲染内容,不需要修改原始数据:
// 封装通用高亮渲染组件 const HighlightText = ({ content, keyword }: { content: string; keyword: string }) => { if (!keyword) return <>{content}</> // 正则转义避免特殊字符报错 const reg = new RegExp(`(${keyword.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`, 'gi') const fragments = content.split(reg) return <> {fragments.map((frag, idx) => reg.test(frag) ? <mark key={idx}>{frag}</mark> : frag )} </> } // 表格列渲染时直接调用 const tableColumns = [ { key: 'expanded', title: '展开内容', render: (row: TableRowRaw) => row.expanded.map((content, idx) => <div key={idx}> <HighlightText content={content} keyword={filterKeyword} /> </div> ) } // 其余列渲染逻辑同理 ]
方案优势
- TypeScript类型完全清晰,无混合类型报错
- 排序、筛选、导出等业务逻辑直接处理纯字符串,无需额外做类型兼容
- 渲染逻辑与数据逻辑完全解耦,修改展示样式不需要改动数据层代码
- 原始数据可复用,不会被渲染层逻辑污染
兼容方案(仅当确实需要混合存储时使用)
如果业务场景确实需要在数据中混合存储字符串和自定义JSX元素,可显式声明联合类型解决TS报错:
type CellItem = string | JSX.Element type CellContent = CellItem[] interface TableRow { col1: CellContent col2: CellContent expanded: CellContent }
注意:该方案需要在做排序、筛选前,先判断数组元素类型,将JSX元素转换为对应的纯文本后再做逻辑处理,会增加额外的兼容代码,非必要不推荐使用。
内容的提问来源于stack exchange,提问作者Erikm
相关产品推荐
相关产品推荐

