afraid-scarlet
afraid-scarlet6mo ago

Set type of table record using useTable

How do I set a type to my table records? I'm currently using Ant Design and the useTable() hook. What changes do I need to make in order to avoid the error commented in my code snippet?
const { tableProps } = useTable({
syncWithLocation: true,
});

return (
<List>
<Table {...tableProps} rowKey="id">
<Table.Column
render={(_, record) => (
<Space size="middle">
<a>Invite {record.name}</a> <!-- 'record' is of type 'unknown'.ts(18046) -->
<a>Delete</a>
</Space>
)}
dataIndex="id"
title={translate("fields.id", "ID")}
/>
<!-- ... -->
</Table>
</List>
)
const { tableProps } = useTable({
syncWithLocation: true,
});

return (
<List>
<Table {...tableProps} rowKey="id">
<Table.Column
render={(_, record) => (
<Space size="middle">
<a>Invite {record.name}</a> <!-- 'record' is of type 'unknown'.ts(18046) -->
<a>Delete</a>
</Space>
)}
dataIndex="id"
title={translate("fields.id", "ID")}
/>
<!-- ... -->
</Table>
</List>
)
7 Replies
kapa.ai
kapa.ai6mo ago
Hi @Chrystian Ferreira. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- To set a type for your table records when using the useTable hook, you need to pass the type as a generic parameter to the useTable function. This will ensure that TypeScript knows the type of the record object in your render function. Here's how you can do it: First, define an interface for your record. For example, if your record has an id and a name, you can define it like this:
interface IRecord {
id: number;
name: string;
}
interface IRecord {
id: number;
name: string;
}
Then, pass this interface as a generic parameter to the useTable function:
const { tableProps } = useTable<IRecord>({
syncWithLocation: true,
});
const { tableProps } = useTable<IRecord>({
syncWithLocation: true,
});
Now, TypeScript should know that record is of type IRecord, and you should be able to access record.name without any TypeScript errors. Here's your updated code:
interface IRecord {
id: number;
name: string;
}

const { tableProps } = useTable<IRecord>({
syncWithLocation: true,
});

return (
<List>
<Table {...tableProps} rowKey="id">
<Table.Column
render={(_, record) => (
<Space size="middle">
<a>Invite {record.name}</a>
<a>Delete</a>
</Space>
)}
dataIndex="id"
title={translate("fields.id", "ID")}
/>
<!-- ... -->
</Table>
</List>
)
interface IRecord {
id: number;
name: string;
}

const { tableProps } = useTable<IRecord>({
syncWithLocation: true,
});

return (
<List>
<Table {...tableProps} rowKey="id">
<Table.Column
render={(_, record) => (
<Space size="middle">
<a>Invite {record.name}</a>
<a>Delete</a>
</Space>
)}
dataIndex="id"
title={translate("fields.id", "ID")}
/>
<!-- ... -->
</Table>
</List>
)
For more information, you can refer to the useTable documentation (https://refine.dev/docs/ui-integrations/ant-design/hooks/use-table). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai6mo ago
<@1072217596058939412> kapa.ai is still learning and improving, please let us know how it did by reacting below
afraid-scarlet
afraid-scarlet6mo ago
@kapa.ai This yields the same result. Looking at the 'render' prop, the type is the following:
(property) render?: ((value: any, record: unknown, index: number) => React.ReactNode | RenderedCell<unknown>) | undefined
(property) render?: ((value: any, record: unknown, index: number) => React.ReactNode | RenderedCell<unknown>) | undefined
kapa.ai
kapa.ai6mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- The type definition you're seeing is coming from Ant Design's Table.Column component, not from the useTable hook. The record parameter in the render function of Table.Column is typed as unknown by Ant Design, which is why you're seeing the TypeScript error. To avoid this error, you can use a type assertion in the render function to tell TypeScript that record is of type IRecord. Here's how you can do it:
interface IRecord {
id: number;
name: string;
}

const { tableProps } = useTable<IRecord>({
syncWithLocation: true,
});

return (
<List>
<Table {...tableProps} rowKey="id">
<Table.Column
render={(_, record) => {
const typedRecord = record as IRecord;
return (
<Space size="middle">
<a>Invite {typedRecord.name}</a>
<a>Delete</a>
</Space>
);
}}
dataIndex="id"
title={translate("fields.id", "ID")}
/>
{/* ... */}
</Table>
</List>
)
interface IRecord {
id: number;
name: string;
}

const { tableProps } = useTable<IRecord>({
syncWithLocation: true,
});

return (
<List>
<Table {...tableProps} rowKey="id">
<Table.Column
render={(_, record) => {
const typedRecord = record as IRecord;
return (
<Space size="middle">
<a>Invite {typedRecord.name}</a>
<a>Delete</a>
</Space>
);
}}
dataIndex="id"
title={translate("fields.id", "ID")}
/>
{/* ... */}
</Table>
</List>
)
In this code, const typedRecord = record as IRecord; is a type assertion that tells TypeScript to treat record as IRecord. Now, you should be able to access typedRecord.name without any TypeScript errors. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai6mo ago
<@1072217596058939412> kapa.ai is still learning and improving, please let us know how it did by reacting below
afraid-scarlet
afraid-scarlet6mo ago
That would work, but I believe my solution is a bit more adequate:
const { tableProps } = useTable({
syncWithLocation: true,
});

return (
<List>
<Table {...tableProps} rowKey="id">
<Table.Column<IRecord> <!-- Add type here! -->
render={(_, record) => ( <!-- '_' is still of type any, 'record' is of type 'IRecord' -->
<Space size="middle">
<a>Invite {record.id}</a>
<a>Delete</a>
</Space>
)}
dataIndex="id"
title={translate("fields.id", "ID")}
/>
</Table>
</List>
)
const { tableProps } = useTable({
syncWithLocation: true,
});

return (
<List>
<Table {...tableProps} rowKey="id">
<Table.Column<IRecord> <!-- Add type here! -->
render={(_, record) => ( <!-- '_' is still of type any, 'record' is of type 'IRecord' -->
<Space size="middle">
<a>Invite {record.id}</a>
<a>Delete</a>
</Space>
)}
dataIndex="id"
title={translate("fields.id", "ID")}
/>
</Table>
</List>
)
AI should fear me just kidding pls dont take my job this solves the problem, i dont know how to mark this thread as solved
fair-rose
fair-rose6mo ago
Hey @Chrystian Ferreira I think we have more time before AI takes over our jobs. I've marked your question as solved here, no worries.