我正在使用 TypeScript 开发自定义 React 表组件,我需要确保作为 props 传递的数据格式正确。该组件接受两个 props:
tableHeadings
:对象数组,其中每个对象都有一个 id (string)
和一个 title (string)
。tableData
:表示表格行的对象数组。每个对象都应具有与 id
中的 tableHeadings
值相对应的键。这是 tableHeadings 和 tableData 的数据示例:
const tableHeadings = [
{
id: 'name',
title: 'Name',
},
{
id: 'job',
title: 'Job',
},
{
id: 'location',
title: 'Color',
},
{
id: 'country',
title: 'Us',
},
];
const tableData = [
{
name: 'Cy Ganderton',
job: 'Quality Control Specialist',
location: 'Canada',
country: 'USA',
},
{
name: 'Hart Hagerty',
job: 'Desktop Support Technician',
location: 'United States',
country: 'USA',
}
];
组件的使用方式如下:
<Table tableHeadings={tableHeadings} tableData={tableData} />
目标是验证
tableData
道具的结构是否与 tableHeadings
道具匹配。具体来说, tableData
中的每个对象都应该具有与 id
中对象的 tableHeadings
值相匹配的键。
id
的 tableHeadings
字段与 tableData
对象的键之间的关系。
为了在 TypeScript 中定义组件及其类型,我编写了以下代码:
// inside Table component
type TableHeadingType = {
id: string;
title: string
};
type TableDataType<K extends TableHeadingType[]> = {
[Key in K[number]['id']]: string;
};
type TableProps<T extends TableHeadingType> = {
tableData: TableDataType<T[]>[];
tableHeadings:T[]
};
export const Table = <T extends TableHeadingType>({ tableHeadings, tableData }: TableProps<T>) => {
const headers = tableHeadings.map((column, index) => {
return (
<th key={`headCell-${index}`} className={''}>
{column.title}
</th>
);
});
const rows = !tableData?.length ? (
<tr>
<td colSpan={tableHeadings.length} className='text-center'>
No data
</td>
</tr>
) : (
tableData?.map((row, index) => {
return (
<tr key={`row-${index}`}>
{tableHeadings.map((column, index2) => {
const value = row[column.id as keyof typeof row] as string;
return <td key={`cell-${index2}`}>{value}</td>;
})}
</tr>
);
})
);
return (
<>
<table className='content-table'>
<thead>
<tr>{headers}</tr>
</thead>
<tbody>{rows}</tbody>
</table>
</>
);
};
但是,根据
tableData
对 tableHeadings
的验证不起作用,并且也不会产生编译时或运行时错误
我该如何解决这个问题?
这里是代码游乐场的链接供参考:https://playcode.io/1812427
如果您可以帮助我解决 TypeScript React 组件中的验证问题,那将非常有帮助。
您可以将
id
字段类型从 string
更改为 enum
,然后使用此 enum
作为 key
处的 Record
的
tableData
enum HeadingIDEnum {
name = 'name',
job = 'job'
...
}
type TableHeadingType = {
id: HeadingIDEnum;
title: string
};
type TableDataType = Record<HeadingIDEnum, string>[]