Skip to content

Type inference when a function is overloaded and the input param is a union of possible inputs #14337

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
ofirgeller opened this issue Feb 27, 2017 · 4 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@ofirgeller
Copy link

If we define a function and two interfaces like this:

    interface A {

    }

    interface B {

    }

    func(type: 'A'): A;
    func(type: 'B'): B;
    func(type: string) {
     /// this function returns an object of type A or B depending on the string input
    }

I would like to be able to call the function like this

var input = <"A"|"B">getInput();
var output = func(input);

And have the return type be A | B. it seems to me this is logicaly consistent. No idea if it is hard to implement.

Syntactic
Does not change the syntax.

Semantic
Error TS2345 Argument of type '"A" | "B"' is not assignable to parameter of type '"B"'.
Type '"A"' is not assignable to type '"B"'.

The compiler is checking if all possible types of input match all the overloads, when in fact we just need
each type to match a single overload.

Emit
No change past the point of inference.

Compatibility
Should not break anything as this example code does not compile at the moment

Other
Can the feature be implemented without negatively affecting compiler performance?
Might even make it marginally faster as we can stop checking when we find the first overload matching the first type in the union and move on to the next.

@mhegazy
Copy link
Contributor

mhegazy commented Feb 27, 2017

While this makes sense for a functions with single parameters it does not work for the general case.

consider:

declare function push(list: number[], value: number);
declare function push(list: string[], value: string);

push(Math.random() ? numberList : stringList, 2);

Please see discussion in #10620.

@mhegazy mhegazy added the Working as Intended The behavior described is the intended behavior; this is not a bug label Feb 27, 2017
@ofirgeller
Copy link
Author

It could work, you just need to check the combinations to make sure they are all correct and then you infer the return type as a union of all the return types of the overloads that matches any of the possible inputs .

In the example you gave these are the the two possible inputs.
number[] * number
string[] * number

The function does not take string[] * number so you get an error.

@mhegazy
Copy link
Contributor

mhegazy commented Feb 27, 2017

Doing the overload resolution on the cartesian product of the types of all parameters is not something that would scale. we recommend adding a signature with the union type.

@ofirgeller
Copy link
Author

It will scale, it will just do so none linearly :)

However think it's not going to be a problem in 99.999% of the cases and even if it is a problem you can cap the number of combinations and at some point give an error telling the developer functions with 100 overloads that gets passed 100 params that are all union types is not what the language builders had in mind.

fs 3.1

@mhegazy mhegazy closed this as completed Apr 21, 2017
@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

2 participants