简体   繁体   中英

Merge discriminated union of object types in Typescript

Is it possible to merge all properties in a discriminated union of object types?

As an example, suppose I have the following type:

type UnionType = { name: string; } | { age: number; } | { visible: boolean; }

Is it possible to then merge these into a single type like this:

// Expect: { name: string; age: number; visible: boolean };
type Props = MagicType<UnionType>;

This is essentially the inverse of the Unionize type from utility-types .

You can turn a union into an intersection using the answer to this question , with all the caveats that come with it:

type UnionToIntersection<U> =
  (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never

If you don't like the way { name: string; } & { age: number; } & { visible: boolean; } { name: string; } & { age: number; } & { visible: boolean; } { name: string; } & { age: number; } & { visible: boolean; } looks, you can ask the compiler to reinterpret it as a single object type by using an identity mapping :

type MagicType<U> = 
  UnionToIntersection<U> extends infer O ? { [K in keyof O]: O[K] } : never;

This gives you the following output:

type Props = MagicType<UnionType>;
/* type Props = {
    name: string;
    age: number;
    visible: boolean;
} */

which is what you want. Hope that helps; good luck!

Playground link to code

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM