简体   繁体   中英

Typescript: Use object values as keys for a new type

I have an Object:

export const CODES = {
   ALPHA: 'alpha',
   OMEGA: 'omega',
}

I want to have a new type which should look like:

export type CODES_OBJECTS = {
 alpha: {},
 omega: {}
}

But obviously since CODES can be changed in the future and get more key-value pairs, I would like to create a general type, which would automatically get all values from CODES as keys. I found this Types from both keys and values of object in Typescript but the solution did not work for my case.

Also if its easier CODES also can be enum.

You can use an indexed access type combined with keyof to get what you want.

Code

type ValuesAsKeys<T extends Record<any, PropertyKey>, NewValue> = Record<T[keyof T], NewValue>

export const CODES = {
   ALPHA: 'alpha',
   OMEGA: 'omega',
} as const;

export type CODES_OBJECTS = ValuesAsKeys<typeof CODES, {}>
/* resolves to type CODES_OBJECTS = {
    alpha: {};
    omega: {};
} */

Playground Link

Explanation

The type ValuesAsKeys takes two generics -- T is the object whose values we want to use as keys (your CODES const) and NewValue is the value that we want to assign to those keys (here it's an empty object {} but you probably want something better).

In order to use the values of T as keys, we have to insist that the values of T are something that can be used as a key. We do that with T extends Record<any, PropertyKey> which uses the built-in type PropertyKey .

We can access the union of all values of T with T[keyof T] which is an indexed access type. We want to create a Record where those are the new keys. So we get Record<T[keyof T], NewValue> .

In order for typescript to see alpha and omega as their literal values and not just string , we use as const when creating CODES .

CODES is a value rather than a type, so we use typeof CODES as T .

Enum Version

The typescript is almost identical if using an enum . The only difference is that you don't need to add as const .

type ValuesAsKeys<T extends Record<any, PropertyKey>, NewValue> = Record<T[keyof T], NewValue>

enum CODES {
   ALPHA = 'alpha',
   OMEGA = 'omega',
}

export type CODES_OBJECTS = ValuesAsKeys<typeof CODES, {}>

Playground Link

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