44

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.

1

3 Answers 3

63

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.

Sign up to request clarification or add additional context in comments.

Comments

49

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

3 Comments

Yeah, it should go to separate answer but it is indeed exactly what I'm looking for! Quite neat trick with as const. Thanks!
The alternative solution didn't work.
Interesting, here is a playground example typescriptlang.org/play?#code/…
4

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.