最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - interface is not assignable to type Record<string, unknown> - Stack Overflow

programmeradmin2浏览0评论

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 also tableData and tableColumns structure? Without that its difficult to produce your error. – Luis Paulo Pinto Commented Jun 7, 2022 at 16:02
Add a ment  | 

3 Answers 3

Reset to default 2 +150

This 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 than Record<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}[] = ...

发布评论

评论列表(0)

  1. 暂无评论