2

I have a bunch of objects that all have a property to discriminate them. And I have them as a union type. Now I want to create a mapping from the discriminated property to the actual type. I can make it myself, but its duplicitous and error prone so I was wondering if there was some way of generating this programmatically with TypeScript. :)

type X = { type: "x", x: number }
type Y = { type: "y", y: number }

type Value = X | Y
type Type = Value["type"]

// Is it possible to generate this?
type TypeToValue = {
    x: X,
    y: Y,
}

// Its useful for stuff like this
function getRecord<T extends Type>(type: T, id: string): TypeToValue[T] {
    return null as any
}
Chet
  • 18,421
  • 15
  • 69
  • 113
  • 1
    Possible duplicate of [Narrowing a return type from a generic, discriminated union in TypeScript](https://stackoverflow.com/questions/46312206/narrowing-a-return-type-from-a-generic-discriminated-union-in-typescript) – jcalz Dec 22 '17 at 01:09

1 Answers1

1

If the signature is always the same as in your post, whereas the value of type must match the associating property (e.g. x | y), you can get away with the following type:

type TypeToValue<T extends Type> = { [P in T]: number } & { type: T }

Which can be used as followed:

declare function getRecord<T extends Type>(type: T, id: string): TypeToValue<T>

const { type, x } = getRecord('x', 'aa');

There is no way to get the corresponding type from the union type that matches the type argument. TS Playground

Shane
  • 3,049
  • 1
  • 17
  • 18