In my current project, I am dealing with two enums named SourceEnum
and TargetEnum
. Each enum has a corresponding function that is called with specific parameters based on the enum value. The expected parameter types are defined by the type mappings SourceParams
and TargetParams
.
enum SourceEnum {
SOURCE_A = 'SOURCE_A',
SOURCE_B = 'SOURCE_B'
}
enum TargetEnum {
TARGET_A = 'TARGET_A',
TARGET_B = 'TARGET_B',
}
interface SourceParams {
[SourceEnum.SOURCE_A]: { paramA: string };
[SourceEnum.SOURCE_B]: { paramB: number };
}
interface TargetParams {
[TargetEnum.TARGET_A]: { paramA: string };
[TargetEnum.TARGET_B]: { paramB: number };
}
function sourceFn<S extends SourceEnum>(source: S, params: SourceParams[S]) { /* ... */ }
function targetFn<T extends TargetEnum>(target: T, params: TargetParams[T]) { /* ... */ }
I have created a mapping that involves functionality to evaluate a target value for each source value. My goal is to ensure that the params
object used in calling sourceFn(x, params)
will also be suitable for the call targetFn(mapping[x](), params)
. To address this requirement, I formulated the following type:
type ConstrainedMapping = {
[K in SourceEnum]: <T extends TargetEnum>() => (SourceParams[K] extends TargetParams[T] ? T : never)
};
const mapping: ConstrainedMapping = {
[SourceEnum.SOURCE_A]: () => TargetEnum.TARGET_A;
// ...
}
However, setting up the mapping
as shown above triggers the following error message:
Type 'TargetEnum.TARGET_A' is not assignable to type '{ paramA: string; } extends TargetParams[T] ? T : never'.
Although my typing seems correct, I cannot grasp why this issue is arising. It appears that TypeScript may struggle with pinpointing the exact enum value at a certain point.
Is there a methodology to accomplish this? I am currently using TypeScript 4.2, but I experimented with versions 4.3 and 4.4-beta as well, all yielding the same outcome. Any solution applicable to 4.2 would be greatly appreciated, although I am open to implementing a future version if necessary.