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