I have an enum, representing type of node in tree structure.
enum MyEnum {
'A' = 'A',
'B' = 'B',
'C' = 'C',
// ...
}
Each node has predefined allowed types of children nodes.
type ChildrenAllowed<T extends MyEnum> = T extends MyEnum.A
? MyEnum.B | MyEnum.C
: T extends MyEnum.B
? MyEnum.C
: undefined;
I would like to have a function, that returns an array of allowed node types. However, I'm getting type errors. Is there something I'm missing?
const getChildrenAllowedTypes = <T extends MyEnum>(
p: T,
): ChildrenAllowed<T>[] => {
switch (p) {
case MyEnum.A:
return [
MyEnum.B, // Err: Type 'E.B' is not assignable to type 'O'.
MyEnum.C, // Err: Type 'E.C' is not assignable to type 'O'.
];
case MyEnum.B:
return [
MyEnum.C, // Err: Type 'E.C' is not assignable to type 'O'.
];
default:
return [];
}
};
This is not related to the problem directly.
// simplified object structure
type ChildrenOwner<TCurrent extends MyEnum> = {
children?: Children<TCurrent>;
};
type Children<
TCurrent extends MyEnum,
TChildrenAllowed = ChildrenAllowed<TCurrent>,
> = {
[TKey in TChildrenAllowed & string]?: TKey extends MyEnum
? ChildrenOwner<TKey>
: undefined;
};
CodePudding user response:
It's always the same problem: TS won't compute the value of ChildrenAllowed<T>
because T
is a generic and is thus undetermined.
I don't know why you get the error not assignable to type 'O'
: it should be not assignable to 'typeChildrenAllowed<T>'
but the bottom line is you need to assert your way out of this.
type ChildrenAllowed<T extends MyEnum> =
T extends MyEnum.A
? MyEnum.B | MyEnum.C
: T extends MyEnum.B
? MyEnum.C
: never; // I think it should be never
const getChildrenAllowedTypes =
<T extends MyEnum>(p: T): ChildrenAllowed<T>[] => {
switch (p) {
case MyEnum.A:
return [
MyEnum.B,
MyEnum.C,
] as ChildrenAllowed<T>[]; // here
case MyEnum.B:
return [
MyEnum.C,
] as ChildrenAllowed<T>[]; // here
default:
return [] as ChildrenAllowed<T>[]; // here
}
};