Skip to content
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

Generic type inference failure with callbacks in 1.4 #1729

Closed
Nemo157 opened this issue Jan 19, 2015 · 3 comments
Closed

Generic type inference failure with callbacks in 1.4 #1729

Nemo157 opened this issue Jan 19, 2015 · 3 comments
Labels
Needs Proposal This issue needs a plan that clarifies the finer details of how it could be implemented. Suggestion An idea for TypeScript

Comments

@Nemo157
Copy link

Nemo157 commented Jan 19, 2015

interface Opts { url: string; }

declare function doit(url: string): number;
declare function doit(opts: Opts): boolean;

declare function call<T, U>(fn: (arg: T) => U, arg: T): U;

var n: number = call(doit, 'here');
var b: boolean = call(doit, { url: 'here' });

In 1.4.1.0 this snippet errors out with

test.ts(8,17): error TS2453: The type argument for type parameter 'T' cannot be inferred from the usage. Consider specifying the type arguments explicitly.
  Type argument candidate 'Opts' is not a valid type argument because it is not a supertype of candidate 'string'.

changing line 8 to ... = call<string, number>(doit, 'here'); successfully compiles as expected.

While playing around with this I noticed that while 1.3.0.0 would allow the call(doit, 'here') invocation it was still choosing the second overload of doit resulting in a return type of boolean and causing a compile error on the assignment. I'm glad 1.4.1.0 is now catching this error case, but it seems like inference of the type parameters should be entirely possible here.

@JsonFreeman
Copy link
Contributor

The issue here was introduced in 1.1. This was because of a change in design with overload resolution.

When we do type argument inference, we have to relate the single signature of fn to the two overloads of doit. In 1.0, we would do this by inferring from both overloads. We would then add string and Opts as candidates, which would produce an error in both calls. This sounds like incorrect behavior.

However, the new behavior is also incorrect. Now, when we infer from two signatures (doit) to one signature (fn), we only infer from the last overload of doit. This causes us to infer Opts in both calls, although in the first call, we also infer string from the second argument, hence the error.

Ideally, we would want the second argument arg to inform our choice of overload. This would involve introducing something akin to contextual signature instantiation when inferring type arguments between groups of signatures. I'd want @ahejlsberg to weigh in as well.

@danquirk danquirk added the Bug A bug in TypeScript label Jan 19, 2015
@JsonFreeman
Copy link
Contributor

This is basically the same problem as #248

@mhegazy mhegazy added this to the TypeScript 2.0 milestone Jan 30, 2015
@JsonFreeman JsonFreeman added the Needs Proposal This issue needs a plan that clarifies the finer details of how it could be implemented. label Jan 30, 2015
@mhegazy mhegazy added the Suggestion An idea for TypeScript label Jul 27, 2015
@mhegazy mhegazy removed the Bug A bug in TypeScript label Jul 27, 2015
@mhegazy mhegazy removed this from the TypeScript 2.0 milestone Jul 27, 2015
@RyanCavanaugh
Copy link
Member

I think we've effectively given up on handling overloads in inference

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs Proposal This issue needs a plan that clarifies the finer details of how it could be implemented. Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

5 participants