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.
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?
>Solution :
You have 2 mistakes.
- line 9 should use
CHILDREN[KEY]instead ofMODULE - line 9 should use
AllMetaDatainstead ofExtractMetaData