Reputation: 47
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.
Upvotes: 1
Views: 2981
Reputation: 42160
You can use an indexed access type combined with keyof
to get what you want.
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: {};
} */
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
.
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, {}>
Upvotes: 1