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

Extract property type from a oneof

I’ve got a type a such:

type OneOf =
  | {
      $case: 'one';
      one: One;
    }
  | {
      $case: 'two';
      two: Two;
    }
  | {
      $case: 'three';
      three: Three;
    };

I want to create a new type to be able to get from the input OneOf, get the output One | Two | Three.

I have tried many different things, including one from this answer with UnionToIntersection in the hope that with an intersection, I could simply exclude the $case, loop on the keys and return the type.

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

I always get a never type as output though.

Essentially, I thought I could get away with it with the following:

type ExtractOneOfTypes<T, K extends keyof T = keyof T> = {
  [key in K]: T extends { $case: key } ? T[key] : never;
}[K];

Because in my oneOf, for each $case, on that same object there is a property name that is the same as the $case value. But this doesn’t work. Any ideas?

>Solution :

You you can infer the literal value type of $case and then check if it’s a keyof T using a nested Conditional Type like so:

type One = { one: string };
type Two = { two: number };
type Three = { three: boolean };

type OneOf =
  | { $case: "one"; one: One }
  | { $case: "two"; two: Two }
  | { $case: "three"; three: Three };

type ExtractOneOfTypes<T, K extends keyof T> = T extends { [Key in K]: infer U }
  ? U extends keyof T
    ? T[U]
    : never
  : never;

type ExtractedType = ExtractOneOfTypes<OneOf, "$case">;
//    ^? type ExtractedType = One | Two | Three

TypeScript Playground

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