I have create a generic react ponent as following:
export interface GenericTableProps<T extends Record<string, unknown>> {
columns: Column<T>[];
data: T[];
}
const GenericTable = <T extends Record<string, unknown>>({
columns,
data,
}: GenericTableProps<T>): ReactElement => {
...
}
This is how I use this ponent:
const data: StudentsDto[] = useMemo(() => tableData ?? [], [tableData]);
const columns: Column<StudentsDto>[] = useMemo(() => tableColumns, []);
<GenericTable columns={columns} data={data} />
This gives me a typescript error:
Type 'StudentsDto[]' is not assignable to type 'Record<string, unknown>[]'.
Type 'StudentsDto' is not assignable to type 'Record<string, unknown>'.
Index signature for type 'string' is missing in type 'StudentsDto'
StudentsDto
looks as following:
export interface StudentsDto {
index?: number;
name?: string;
lastName?: string;
dob?: string;
...
}
I should mention that I can't update StudentsDto
interface, since it's generated using openApi.
How can I solve this ?
I have create a generic react ponent as following:
export interface GenericTableProps<T extends Record<string, unknown>> {
columns: Column<T>[];
data: T[];
}
const GenericTable = <T extends Record<string, unknown>>({
columns,
data,
}: GenericTableProps<T>): ReactElement => {
...
}
This is how I use this ponent:
const data: StudentsDto[] = useMemo(() => tableData ?? [], [tableData]);
const columns: Column<StudentsDto>[] = useMemo(() => tableColumns, []);
<GenericTable columns={columns} data={data} />
This gives me a typescript error:
Type 'StudentsDto[]' is not assignable to type 'Record<string, unknown>[]'.
Type 'StudentsDto' is not assignable to type 'Record<string, unknown>'.
Index signature for type 'string' is missing in type 'StudentsDto'
StudentsDto
looks as following:
export interface StudentsDto {
index?: number;
name?: string;
lastName?: string;
dob?: string;
...
}
I should mention that I can't update StudentsDto
interface, since it's generated using openApi.
How can I solve this ?
Share Improve this question asked Jun 1, 2022 at 18:44 Renaud is Not Bill GatesRenaud is Not Bill Gates 2,12438 gold badges115 silver badges212 bronze badges 1-
What about
Column
->columns: Column<T>[];
. It´s some interface that you created or some 3rd library ? Can you add it and alsotableData
andtableColumns
structure? Without that its difficult to produce your error. – Luis Paulo Pinto Commented Jun 7, 2022 at 16:02
3 Answers
Reset to default 2 +150This error is due to typescript's type inference (here's the official doc, and a related answer that can help to understand it)
As @subrato-pattanaik well spotted, unknown
should be used when you will narrow types afterwards. And you can use any
to accept any type.
For your particular case, if you need to make the interface GenericTableProps
to accept different types...
and some of them you do not know at the moment: I'd use an
object
type, since it is more readable thanRecord<string, any>
(differences here)export interface GenericTableProps<T extends object> { //...
and you know all of them: I'd create a new interface extending all the types that
GenericTableProps
can accept, and use that particular type. This approach is the preferred one because you will have narrower types, and that can help you avoid type errors.interface GenericTableDataType extends StudentsDto, ProfessorsDto {} export interface GenericTableProps<T extends GenericTableDataType> { //...
The most direct answer is to use Record<string, any>
instead of Record<string, unknown>
. The general use case of unknown
type is when we have to narrow down the types. For example,
function fn(g: unknown) {
if(typeof g === 'string'){
g; //here g would be string
console.log(g.toLowerCase()); // typescript will not yell us about wrong types
}
if(typeof g === 'function'){
g; // function type
console.log(g.name); // can access name property of function
}
}
With Record<string, any>
type means that we are assured that it will match with any object
and not any type
whether they have inferred index signature or not.
The obvious reason why it works with Record<string, any>
and not Record<string, unknow>
is given here in this issue.
You can either remove extends Record<string, unknown>
or add an index signature to your type const data: StudentsDto & {[key: string]: unknown}[] = ...