Home > Back-end >  Mapped type that unions variations of the given type?
Mapped type that unions variations of the given type?

Time:12-15

Given a type that contains all possibilities (e.g. non-tagged union):

type Input = {
  a: string,
  b: number,
  c: boolean,
};

I want to map it with this kind of API:

type MapItSomehow<T> = ???;

type Output = MapItSomehow<Input>;

And ultimately get this:

type Output = {
  a: string,
  b: undefined,
  c: undefined,
} | {
  a: undefined,
  b: number,
  c: undefined,
} | {
  a: undefined,
  b: undefined,
  c: boolean,
};

The proof that this works is if I can do:


let r: Result = ([] as Result[])[0];

if ('a' in r) {
  r.a.trim() // not r.a!.trim()
}
else if // same for each field ...

CodePudding user response:

It is possible to do with mapped types, Record and Exclude:

type Input = {
  a: string,
  b: number,
  c: boolean,
};

type Values<T> = T[keyof T]

type Mapped<T> = Values<{
  [Prop in keyof T]: Record<Prop, T[Prop]>
}>


type Result = Mapped<Input>

declare let x: Result

if ('a' in x) {
  x.a.trim()
}

Playground

Mapped - iterates through each property and creates new part of expected union type where current key is set and other keys Exclude<keyof T, Prop> are undefined

Values - obtains a union type of all object values

  • Related