Reputation: 1327
I'm in the process of moving from flow to typescript and I've run into something I can't figure out how to do. In flow I had the following:
const color = Object.freeze({
white: '#ffffff',
black: '#000000',
})
type PossibleColorValues = $Values<typeof color>
in this case PossibleColorValues
was '#ffffff' | '#000000'
Is there an equivalent to this in typescript? I've tried the following:
type PossibleColorValues = typeof color[keyof typeof color]
but in this case PossibleColorValues
is just string
Upvotes: 1
Views: 48
Reputation: 250366
You have the right idea about how to get a union of all possible values in an object. typeof color[keyof typeof color]
should do the trick.
The problem is that color
does not preserve original types as it is currently defined. You need to convince the compiler to preserve the string literal types you originally assign in the object literal.
In 3.4, unreleased yet, you can use as const
to let the compiler know you want literal types and a readonly object. So this will work as expected in 3.4 (again when 3.4 is released probably this month):
const color = Object.freeze({
white: '#ffffff',
black: '#000000',
} as const)
type PossibleColorValues = typeof color[keyof typeof color]
In the meantime you can use a function to get the compiler to infer literal types:
declare function withLiterals<
T extends Record<string, V>,
V extends string | boolean | number | symbol | null | undefined | Record<string, V>
>(input: T ): T;
const color = Object.freeze(withLiterals({
white: '#ffffff',
black: '#000000',
}));
type PossibleColorValues = typeof color[keyof typeof color]
Upvotes: 1