Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Typescript union type to object type

Is it possible to translate a type of this kind:

export type UnionType = {
    element:
        | { $case: 'a'; a: number }
        | { $case: 'b'; b: string }
        | { $case: 'c'; c: boolean };
};

to a type of a kind:

type OneOfConverter<T> = any; // TODO

type ObjectType = OneOfConverter<UnionType>;

// type ObjectType = {
//     a: number;
//     b: string;
//     c: boolean;
// };

Typescript playground

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

My suggestion here would be:

type OneOfConverter<T extends { element: { $case: PropertyKey } }> = {
    [U in T["element"] as U["$case"]]: U["$case"] extends keyof U ? U[U["$case"]] : never
}

It uses key remapping in mapped types to iterate over the union members of T['element'] (an indexed access type corresponding to the type of the element property of the type T passed in) and put each member of that union into a type parameter U. Then the key we want is U["$case"].

For each value we pretty much want to index into U with that key, so U[U["$case"]], but the compiler doesn’t know if that member really will exist (maybe you pass in { $case: "z" } and the z property doesn’t appear for some reason). So we have to address its concern by first doing the conditional type check U["$case"] extends keyof U, which compares the desired key to the keys of U. If it exists, we grab the property value as U[U["$case"]]. If it doesn’t, then we return never for want of anything better.

Let’s make sure it works:

type ObjectType = OneOfConverter<UnionType>;
// type ObjectType = {
//     a: number;
//     b: string;
//     c: boolean;
// };

Looks good!

Playground link to code

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading