I'm trying to get return type based on exact string from parameter.
Here is what I have so far (without curring):
type Simple = {
(side: 'left'): boolean;
(side: 'right'): number;
};
const simple: Simple = (side: 'left' | 'right') =>
(side === 'left' ? random([true]) : random([1])) as boolean & number;
const simpleLeft = simple('left'); // boolean ✔️
const simpleRight = simple('right'); // number ✔️
Then I just add curring and it doesn't work anymore
type Hard = {
(): (side: 'left') => boolean;
(): (side: 'right') => number;
};
const hard: Hard = () => (side: 'left' | 'right') =>
(side === 'left' ? random([true]) : random([1])) as boolean & number;
const hardLeft = hard()('left'); // boolean ✔️
const hardRight = hard()('right'); // boolean ❌
random function is there to just get generic type like boolean
instead of false
or true
const random = <T>(array: T[]) =>
array[Math.floor(Math.random() * array.length)] as T;
Code above is just an example demonstrating problem, I can't just not use curring because it is a part of big code base
CodePudding user response:
I am not sure why you need currying here. But if you want this to compile correctly you need to put the function overload inside the first function signature.
type Hard = {
(): {
(side: 'left'): boolean;
(side: 'right'): number;
}
};
Now the compiler can decide which overload to choose based on the input of the second function.
const hardLeft = hard()('left'); // boolean ✔️
const hardRight = hard()('right'); // number ✔️
CodePudding user response:
That type Hard
just looks like an invalid function overload to me. When evaluating hard()
, there is no way for the compiler to infer which of the two signatures you're referring to.
I don't know if it fits your needs, but you could use a generic constraint with a conditional type:
type Hard = {
(): <T extends 'left' | 'right'>(side: T)
=> T extends 'left' ? boolean :
T extends 'right' ? number : never;
};
const hard: Hard = () => (side: 'left' | 'right') =>
(side === 'left' ? random([true]) : random([1])) as boolean & number;
const hardLeft = hard()('left'); // boolean ✔️
const hardRight = hard()('right'); // number ✔️
const random = <T>(array: T[]) =>
array[Math.floor(Math.random() * array.length)] as T;