React表格组件TypeScript类型推断问题:无需显式标注实现格式化行推导
TypeScript类型推断问题:React表格组件中rowFormatter的自动类型推导
我在为React表格组件编写TypeScript类型时遇到了类型推断异常:传入数据后希望自动推断原始数据类型,但引入用于修改数据并返回新类型的rowFormatter函数后,若不显式标注rowFormatter的参数类型,getRow函数的参数类型会被推断为unknown。
简化后的类型定义如下:
type Props<TRow, TFormattedRow> = { data: TRow[] getRow?: (row: TFormattedRow) => void rowFormatter: (row: TRow) => TFormattedRow } function createProps<TRow, TFormattedRow>(props: Props<TRow, TFormattedRow>) { return props }
正常工作的场景(显式标注rowFormatter参数类型)
当显式标注rowFormatter的参数类型时,getRow能正确推断格式化后的行类型为{ id: string, name: string, count: number }:
createProps({ data: [ { id: '1', name: 'Mangus Karlsson', count: 4 }, { id: '2', name: 'Elsa Nyström', count: 6 }, { id: '3', name: 'Bengt Blyertz', count: 8 }, ], // getRow正确推断formattedRow类型为{ id: string, name: string, count: number } getRow: (formattedRow) => console.log(formattedRow), rowFormatter: (row: { id: string, name: string, count: number }) => { return { id: row.id, idAsNumber: parseInt(row.id) } }, })
类型推断异常的场景(不显式标注rowFormatter参数类型)
若不标注rowFormatter的参数类型,getRow的formattedRow参数类型会被推断为unknown:
createProps({ data: [ { id: '1', name: 'Mangus Karlsson', count: 4 }, { id: '2', name: 'Elsa Nyström', count: 6 }, { id: '3', name: 'Bengt Blyertz', count: 8 }, ], // formattedRow被推断为unknown getRow: (formattedRow) => console.log(formattedRow), rowFormatter: (row) => { return { id: row.id, idAsNumber: parseInt(row.id) } }, })
问题原因
原类型定义中,TypeScript需要同时推断TRow和TFormattedRow两个泛型参数,但当rowFormatter参数未标注类型时,TypeScript无法确定row的类型,导致TRow推断失败,进而TFormattedRow被默认推断为unknown。
解决方案
调整泛型定义,让TypeScript先从data推断出原始行类型TRow,再基于rowFormatter的返回值自动推导格式化后的行类型。可以通过拆分泛型依赖关系实现:
// 提取rowFormatter的返回值类型作为格式化行类型 type FormattedRow<TRow, F extends (row: TRow) => any> = ReturnType<F> type Props<TRow, F extends (row: TRow) => any> = { data: TRow[] getRow?: (row: FormattedRow<TRow, F>) => void rowFormatter: F } function createProps<TRow, F extends (row: TRow) => any>(props: Props<TRow, F>) { return props }
测试验证
使用调整后的定义,无需显式标注rowFormatter的参数类型,getRow就能正确推断格式化后的行类型:
createProps({ data: [ { id: '1', name: 'Mangus Karlsson', count: 4 }, { id: '2', name: 'Elsa Nyström', count: 6 }, { id: '3', name: 'Bengt Blyertz', count: 8 }, ], // formattedRow自动推断为{ id: string; idAsNumber: number; } getRow: (formattedRow) => console.log(formattedRow.idAsNumber), rowFormatter: (row) => { return { id: row.id, idAsNumber: parseInt(row.id) } }, })
原理说明
- 先通过
data推断出原始行类型TRow - 再将
rowFormatter的类型约束为接收TRow参数的函数,TypeScript会自动推导其返回值类型作为FormattedRow getRow的参数类型直接关联FormattedRow,从而实现自动推断
内容的提问来源于stack exchange,提问作者Filip Kantedal
相关产品推荐
相关产品推荐

