简体   繁体   中英

How to define a typescript type for a dictionary with generic keys?

While trying to map the keys of data I'm getting several Typescript errors and I don't understand why. I'm getting back as a response from my API an object with generic keys as followed:

{
  1: { 
      name: 'test1',
      country: 'test1',
  },
  2: {
       name: 'test2',
      country: 'test2',
  }
  ....generic amount of keys
}

I have defined the following typescript type for this:

export type Users<T> = {
  [K in keyof T]: {
    name: string;
    country: string;
  };
};

When I'm trying to map on the keys of this typed object in my component I'm gtting an error from typescript:

Object.keys(data).map((key) => {
  <p>{data[key].name}</p>
})

Error on Object.keys(data) line:

const data: Users | undefined No overload matches this call.
Overload 1 of 2, '(o: {}): string[]', gave the following error. Argument of type 'Users | undefined' is not assignable to parameter of type '{}'. Type 'undefined' is not assignable to type '{}'. Overload 2 of 2, '(o: object): string[]', gave the following error. Argument of type 'Users | undefined' is not assignable to parameter of type 'object'. Type 'undefined' is not assignable to type 'object'.ts(2769) No quick fixes available

Error on data[key].name:

Object is possibly 'undefined'.

From the TSConfig reference noUncheckedIndexedAccess :

TypeScript has a way to describe objects which have unknown keys but known values on an object, via index signatures.

Turning on noUncheckedIndexedAccess will add undefined to any un-declared field in the type.

You can use the non-null assertion operator (postfix ! ) to inform the compiler that the value definitely exists. Here's an example:

TS Playground

import {default as React} from 'react';

type User = {
  name: string;
  country: string;
}

const data: Record<string, User> = {
  1: { 
    name: 'test1',
    country: 'test1',
  },
  2: {
    name: 'test2',
    country: 'test2',
  },
  // ....generic amount of keys
};

Object.keys(data).map(key => (<p>{data[key]!.name}</p>));
//                                         ^
// The non-null assertion operator will assert
// to the compiler that the value exists

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM