Reputation: 26142
Say I have an indexed type:
type X = {
a: 'A',
b: 'B'
}
is it possible to get (derived) from it:
type V = 'A' | 'B'
not using explicit method like:
type V = X['a'] | X['b']
What I want is something like keyof
(for getting keys union type), but for values.
Upvotes: 44
Views: 24247
Reputation: 35914
I realize this has already been answered, but if you are looking for a way to narrow your union to actual values instead of primitives and you are working with immutable state, you can do this:
const X = {
a: 'A',
b: 'B'
// mark properties as readonly, otherwise string type inferred
} as const
type XValues = typeof X[keyof typeof X]
// "A" | "B
Alternatively, if you are working with both mutable and immutable copies, creating a separate readonly type could be useful:
const X = {
a: 'A',
b: 'B'
}
type X = Readonly<typeof X>
type XValues = keyof X
// "A" | "B
Upvotes: 49
Reputation: 346
In case someone wants to do this for a union of types, instead of just one type, this works perfectly:
type allSubTypesOfUnionType<T> = T extends any ? T[keyof T] : never
So if you have a union of 2 types:
type cheese = {
name: string
holes: number
}
type pizza = {
slices: number
isPepperoni: boolean
}
type yellowFood = cheese | pizza
You can then create a type that extracts all the sub-types as a union:
type possibleTypesOfYellowFood = allSubTypesOfUnionType<yellowFood>
// types is: number | string | boolean
This was adapted from this answer that did the same but for keys instead of sub-types.
Upvotes: 4
Reputation: 249646
You can use a type query with the result of keyof
:
type V = X[keyof X]
Generally a type query will return a union of all possible field types, so X['a'] | X['b']
is the same as X['a' | 'b']
. This is why X[keyof X]
works, as keyof
will return a union of string literal types representing all keys in the object.
Upvotes: 63