联合给定类型变体的映射类型?

Mapped type that unions variations of the given type?

给定一个包含所有可能性的类型(例如非标记联合):

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

我想用这种方式映射API:

type MapItSomehow<T> = ???;

type Output = MapItSomehow<Input>;

最终得到这个:

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

如果我能做到的话,证明这是可行的:


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

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

可以用 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 - 遍历每个 属性 并创建预期联合类型的新部分,其中设置了当前键,其他键 Exclude<keyof T, Prop>undefined

Values - 获取所有对象值的联合类型