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 type recursion over object

I have these definitions for a Module, which contains a MetaData type and an object that maps arbitrary names to child/nested Modules:

type Module<T, C extends Children> = {
    metaData: T;
    children: C;
};

type Children = {
    [key: string]: Module<any, any>;
}

type ExtractMetaData<M extends Module<any, any>> = M extends Module<infer T, any> ? T : never;

type ExtractChildren<M extends Module<any, any>> = M extends Module<any, infer C> ? C : never;

Now, let’s say I define three simple modules, A, B, and C, so that C is a child of B and B is a child of A:

type C = Module<number, {}>;

type B = Module<boolean, {
  c: C;
}>;

type A = Module<string, {
  b: B;
}>;

What I want is a utility type AllMetaData<T extends Module> that will return a union of all the MetaData types in a Module tree. For example, AllMetaData<C> is the type number, AllMetaData<B> is the type number | boolean, and AllMetaData<A> is the type number | boolean | string.

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

Here’s what I have:

type AllMetaData<
  MODULE extends Module<any, any>,
  CHILDREN = ExtractChildren<MODULE>,
  METADATA = ExtractMetaData<MODULE>,
> =
  | METADATA
  | {
      [KEY in keyof CHILDREN]: CHILDREN[KEY] extends Module<any, any>
        ? ExtractMetaData<MODULE>
        : never;
    }[keyof CHILDREN];

But it doesn’t seem to work, because when I define this type:

type Result = AllMetaData<A>;

Result is equivalent to string, when it should be a union of all the MetaData types in A’s tree.

Why doesn’t my AllMetadata type work?

Playground link

>Solution :

You have 2 mistakes.

  1. line 9 should use CHILDREN[KEY] instead of MODULE
  2. line 9 should use AllMetaData instead of ExtractMetaData

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