已经2天了,我一直在努力制作一个可重复使用的表,但是我遇到了类型的问题。
我不是打字稿/反应专家,因为我与javascript在一起工作更多,所以我想向您展示开发此组件的正确方法。
信息:
typescript: "3.6.4"
react: "^16.11.0"
"engines": {
"node": "10.x",
"npm": "6.x"
}
我的想法是(不完整且有类型错误):
import * as React from 'react';
const getCellData = (fields: Record<string, string>, row) => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return Object.entries(fields).reduce((res: Record<string, any>, val) => {
res[val[0]] = row[val[1]];
return res;
}, {});
};
interface Props<C, R> {
columns: C[];
rows: R[];
}
const Table = <C, R>({ columns, rows }: Props<C, R>) => {
return (
<div className="table-responsive">
<table className="table table-striped">
<thead>
<tr>
{columns.map((column, i: number) => (
<th scope="col" key={i}>
{column.label}
</th>
))}
</tr>
</thead>
<tbody>
{rows &&
rows.map((row, j: number) => {
return (
<tr key={j}>
{columns.map((column, k: number) => {
const { Template, fields } = column;
const data = getCellData(fields, row);
return <td key={k}>{<Template {...data}></Template>}</td>;
})}
</tr>
);
})}
</tbody>
</table>
</div>
);
};
export default Table;
我正在JSX中使用这样的表(像这样在jsx中传递类型正确吗?)
<Table<SportsTableColumn, RedaxSport> columns={columns} rows={sports}></Table>
其中SportsTableColumn为:
export interface SportsTableColumn {
label: string;
Template: typeof TableTdText | typeof TableTdTextWithImage | typeof TableTdBoolCheck;
fields: {
text?: string;
image?: string;
checked?: string;
};
}
TableTdText,TableTdTextWithImage,TableTdBoolCheck是React.FC
然后我们有RedaxSport,它是一个具有以下属性的类:
this.sportId = sportId;
this.urlIcon = urlIcon;
this.redaxDescription = redaxDescription;
this.aamsDescription = aamsDescription;
this.isDailyProgram = isDailyProgram;
“列”数组数据示例:
[
{
label: intl.formatMessage({ id: 'sports.table.redaxDescription' }),
Template: TableTdTextWithImage,
fields: {
text: 'redaxDescription',
image: 'urlIcon'
}
},
{
label: intl.formatMessage({ id: 'sports.table.aamsDescription' }),
Template: TableTdText,
fields: {
text: 'aamsDescription'
}
},
{
label: intl.formatMessage({ id: 'sports.table.dailyProgram' }),
Template: TableTdBoolCheck,
fields: {
checked: 'isDailyProgram'
}
}
];
“行”数据示例:
[
{
"sportId": 0,
"urlIcon": "https://url.com/",
"redaxDescription": "This is a description",
"aamsDescription": "Another description",
"isDailyProgram": true
},
{
"sportId": 1,
"urlIcon": "https://url2.com/",
"redaxDescription": "This is a description 2",
"aamsDescription": "Another description 2",
"isDailyProgram": false
}
]
我只是希望清楚我的意图,并为您提供所需的所有信息。 谢谢
答案 0 :(得分:1)
U必须为您的列提供类型或接口,例如:
interface IColumn {
label: string;
fields: { [key: string]: string };
Template: React.ComponentClass;
};
对表组件中的C泛型说,它接受扩展该接口的所有内容
const Table = <C extends IColumn, R>({ columns, rows }: Props<C, R>) => {...}
因此,这将使您的组件知道它可以使用IColumn
界面中的任何字段。
然后用SportsTableColumn
扩展IColumn
export interface SportsTableColumn extends IColumn {
label: string;
Template: React.ComponentClass;
fields: {
text?: string;
image?: string;
checked?: string;
};
}
注意:将React.ComponentClass
替换为TdComponents
答案 1 :(得分:0)
我将Template: React.ComponentClass;
替换为Template: typeof TableTdText | typeof TableTdTextWithImage | typeof TableTdBoolCheck;
,但是我得到了
Type 'SportsTableColumn' does not satisfy the constraint 'Column'.
Types of property 'Template' are incompatible.
Type 'FunctionComponent<OwnProps> | FunctionComponent<OwnProps> | FunctionComponent<OwnProps>' is not assignable to type 'ComponentClass<{}, any>'.
Type 'FunctionComponent<OwnProps>' is not assignable to type 'ComponentClass<{}, any>'.
Type 'FunctionComponent<OwnProps>' provides no match for the signature 'new (props: {}, context?: any): Component<{}, any, any>'.
谢谢您的帮助!