The use case is as follows:
First, I have an interface called Test1
which maps between a certain key and a type.
Next, I have a second interface, Test2
, which maps between those same keys and different types.
Third, I have functions (as values in mapper
object) that know how to map between the first to the second.
Essentially, the use case is the need to map between different objects that are connected by some key, but to make it as generic as possible while constraint by the interfaces that holds the mappings.
The following code
interface Test1 {
a: number;
b: string;
}
interface Test2 {
a: object;
b: Array<number>;
}
type Mapper = {
[P in keyof Test1]: (param: Test2[P]) => Test1[P];
};
const mapper: Mapper = {
a: (param: object) => 123,
b: (param: Array<number>) => 'asd'
};
function test<T extends keyof Test1>(type: T, msg: Test2[T]): Test1[T] {
const func = mapper[type];
return func(msg);
}
throws the following exception when trying to pass msg
to func
:
Argument of type `Test2[T]` is not assignable to parameter of type `number[]`.
In this example, lets assume type
will be equal to 'a'
, then I want to receive the function that the mapper
holds as value of key 'a'
and use it on the msg
I have.
I did see this` issue when searching for a solution, but I thought maybe my case is differnet, reason being that I'm using a mapped type.
Any way to work this out? Thanks!
The issue stems from the fact that the type of func
is inferred to be (param: object & number[]) => 'number | string'
which narrows to (param: number[]) => 'number | string'
The typescript compiler is simply not smart enough to realize that the parameters signature of func
always matches Test2[T]
.
Unfortunately, your best solution is probably to just cast and tell the compiler that you know better.
function test<T extends keyof Test1>(type: T, msg: Test2[T]): Test1[T] {
const func = mapper[type] as any;
return func(msg);
}