I'm working on build an editable table using antd in typescript, following the guide antd: table edit row.
For now it works fine as an editable table, whether editing or displaying data.
However, since i'm using typescript, there're some errors with column type.
Here's my Item definition and column value.
interface CleanFilterItemLabel {
key: string;
name: string;
color?: string;
}
interface CleanFilterItem {
id: React.Key,
state: string,
keyword: string,
create_at: number,
edit_at: number,
author?: string,
level?: number,
group?: number,
labels?: CleanFilterItemLabel[];
}
const edit_tabel_column = [
{
title: t("editPage.level"),
dataIndex: 'level',
editable: true,
},
// {
// title: t("editPage.labels"),
// dataIndex: 'labels',
// editable: true,
// render: (labels: any) => (
// <>
// {labels.map((label: any) => {
// return (
// <Tag key={label.key}>
// {label.name}
// </Tag>
// )
// })}
// </>
// ),
// },
{
title: t("editPage.group"),
dataIndex: 'group',
editable: true,
},
{
title: t("editPage.state"),
dataIndex: 'state',
editable: true,
filters: [
{
text: t("editPage.enabled"),
value: 'open',
},
{
text: t("editPage.disabled"),
value: 'closed'
}
],
filterSearch: false,
onFilter: (value: string, record: any) => record.state === value,
render: (state: string) => (
<>
{state === 'open' ? <Badge status="error" text={t("editPage.disabled")}/> : <Badge status="success" text={t("editPage.enabled")}/>}
</>
),
},
{
title: t("editPage.keyword"),
dataIndex: 'keyword',
editable: true,
ellipsis: {
showTitle: false,
},
...getColumnSearchProps('keyword'),
},
{
title: t("editPage.createAt"),
dataIndex: 'create_at',
ellipsis: {
showTitle: false,
},
editable: false,
sorter: (a: any, b: any) => a.create_at - b.create_at,
render: (create_at: number) => (
<Tooltip title={time.get_date_string_from_timestamp(create_at, "YYYY-MM-DD")} placement='top'>
{time.get_date_string_from_timestamp(create_at, "YYYY-MM-DD")}
</Tooltip>
),
},
{
title: t("editPage.editAt"),
dataIndex: 'edit_at',
ellipsis: {
showTitle: false,
},
editable: false,
sorter: (a: any, b: any) => a.edit_at - b.edit_at,
render: (edit_at: number) => (
<Tooltip title={time.get_date_string_from_timestamp(edit_at, "YYYY-MM-DD")}>
{time.get_date_string_from_timestamp(edit_at, "YYYY-MM-DD")}
</Tooltip>
),
},
{
title: t("editPage.operation"),
dataIndex: 'operation',
render: (_: any, record: CleanFilterItem) => {
const editable = isEditing(record);
return editable ? (
<span>
<Typography.Link onClick={() => saveEditingRow(record.id)} style={{ marginRight: 8 }}>
{t('editPage.save')}
</Typography.Link>
<Popconfirm title={t("editPage.sureToCancel")} onConfirm={cancelEditTableRow}>
<a>{t('editPage.cancel')}</a>
</Popconfirm>
</span>
) : (
<div>
<Typography.Link disabled={editingKey !== ''} onClick={() => editTableRow(record)}>
{t('editPage.edit')}
</Typography.Link>
<Divider type="vertical" />
<Typography.Link disabled={editingKey !== ''} onClick={() => removeRow(record)}>
{t('editPage.delete')}
</Typography.Link>
</div>
);
},
}
]
const mergedEditColumns = edit_tabel_column.map((col) => {
if (!col.editable) {
return col;
}
return {
...col,
onCell: (record: CleanFilterItem) => ({
record,
inputType: col.dataIndex,
dataIndex: col.dataIndex,
title: col.title,
editing: isEditing(record),
}),
};
})
<Form form={form} component={false}>
<Table
components={{
body: {
cell: EditableCell
}
}}
rowSelection={rowSelection}
columns={mergedEditColumns} // here comes types error
className={style.customTable}
dataSource={tableData}
pagination={{ pageSize: 5 }}
scroll={{ y: 360 }}
rowKey={"id"}
/>
</Form>
and it leads to the following errors
Type '({ title: string; dataIndex: string; editable: boolean; filters?: undefined; filterSearch?: undefined; onFilter?: undefined; render?: undefined; ellipsis?: undefined; sorter?: undefined; } | { title: string; ... 7 more ...; sorter?: undefined; } | ... 6 more ... | { ...; })[]' is not assignable to type '(ColumnType<CleanFilterItem> | ColumnGroupType<CleanFilterItem>)[]'.
Type '{ title: string; dataIndex: string; editable: boolean; filters?: undefined; filterSearch?: undefined; onFilter?: undefined; render?: undefined; ellipsis?: undefined; sorter?: undefined; } | { title: string; ... 7 more ...; sorter?: undefined; } | ... 6 more ... | { ...; }' is not assignable to type 'ColumnType<CleanFilterItem> | ColumnGroupType<CleanFilterItem>'.
Type '{ title: string; dataIndex: string; editable: boolean; filters: { text: string; value: string; }[]; filterSearch: boolean; onFilter: (value: string, record: any) => boolean; render: (state: string) => JSX.Element; ellipsis?: undefined; sorter?: undefined; }' is not assignable to type 'ColumnType<CleanFilterItem> | ColumnGroupType<CleanFilterItem>'.
Type '{ title: string; dataIndex: string; editable: boolean; filters: { text: string; value: string; }[]; filterSearch: boolean; onFilter: (value: string, record: any) => boolean; render: (state: string) => JSX.Element; ellipsis?: undefined; sorter?: undefined; }' is not assignable to type 'ColumnType<CleanFilterItem>'.
Types of property 'onFilter' are incompatible.
Type '(value: string, record: any) => boolean' is not assignable to type '(value: string | number | boolean, record: CleanFilterItem) => boolean'.
Types of parameters 'value' and 'value' are incompatible.
Type 'string | number | boolean' is not assignable to type 'string'.
Type 'number' is not assignable to type 'string'.ts(2322)
InternalTable.d.ts(14, 5): The expected type comes from property 'columns' which is declared here on type 'IntrinsicAttributes & TableProps<CleanFilterItem> & { children?: ReactNode; } & { ref?: Ref<HTMLDivElement> | undefined; }'
I've checked this question columns type error when using a custom sorter function on Ant Design table and try add the following definition to my column, but it still fails
const edit_tabel_column: (ColumnsType<CleanFilterItem> & {editable?: boolean}[]) = []
I'm not good at such a complex type definiation, so how should i give it a proper definition?
The problem is the column onFilter
type has a type definition
value: string | number | boolean, record: Item
If we define our own onFilter
type with definition like
value: number, record: Item
It will throw errors, claim tha value: number
is not compatiable with value: string | number | boolean
.
The solution is to let them have the same type definition as string | number | boolean
.
And here's my reproduction link Once on editable table columns has onFilter property, typescript claims that mergedColumns is not assignable type with columns