简体   繁体   中英

Typescript - Dynamic Generics Type

I don't know what exactly to call this problem but this is my case.

I want defaultValue to automatically get type based on id value.

type User = {
  name: string;
  age: number;
};

type PropConfig<T, K extends keyof T> = {
  id: K;
  label: string;
  defaultValue: T[K];
};

const config: PropConfig<User, 'age'> = {
  id: 'age',
  label: 'Age',
  defaultValue: 18,
};

This is what I want:

type PropConfig<T, K = keyof T> = {
  id: K;
  label: string;
  defaultValue: T[K]; // Error here
};

const config: PropConfig<User> = {
  id: 'age',
  label: 'Age',
  defaultValue: 18,
};

Can someone help me?

TypeScript doesn't have partial type argument inference as proposed in ms/TS#26242 so there's no way to specify T while having the compiler infer K , at least not without workarounds involving curried helper functions or dummy parameters (see Typescript: infer type of generic after optional first generic for more info).

Luckily, I don't think you want PropConfig to be generic in K . Instead, you want PropConfig<T> to be a union of the possible types for each K in keyof T . That is, you want to distribute the type across unions in keyof T . There are a number of ways to do that, but the one I usually do is to make what's called a distributive object type , as coined in ms/TS#47109 . It looks like this:

type PropConfig<T> = { [K in keyof T]-?: {
  id: K;
  label: string;
  defaultValue: T[K];
} }[keyof T]

I immediately index into a mapped type , producing the following for PropConfig<User> :

type PropConfigUser = PropConfig<User>;
/* type PropConfigUser = {
    id: "name";
    label: string;
    defaultValue: string;
} | {
    id: "age";
    label: string;
    defaultValue: number;
} */

which is the type you want:

const config: PropConfig<User> = {
  id: 'age',
  label: 'Age',
  defaultValue: 18,
};

Playground link to code

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