Skip to content

loss of type safety when using function overloads with callbacks #13430

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
rkirov opened this issue Jan 12, 2017 · 6 comments
Closed

loss of type safety when using function overloads with callbacks #13430

rkirov opened this issue Jan 12, 2017 · 6 comments
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed Fix Available A PR has been opened for this issue

Comments

@rkirov
Copy link
Contributor

rkirov commented Jan 12, 2017

TypeScript Version: 2.1.4
Code

declare function it(f: () => void): number;
declare function it(f: (x: string) => void): string;

let r = it((x) => {x});

Expected behavior:
The inferred type of x inside the closure should be string.

Actual behavior:
The inferred type of x is any. Moreover, this triggers noImplicitAny errors.

It appears that the first overload somehow throws off the type inference (no issue without overloads). However, the resulting type of r is string thus the second overload was ultimately chosen. Despite that, the type of x is not inferred to match the one in the overload.

This example worked as expected in TS 2.0.x so it appears to be a regression.

//cc @calebegg

@aluanhaddad
Copy link
Contributor

declare function it(f: (x: string) => void): string;
declare function it(f: () => void): number;

The more specific overload needs to be declared first.

@rkirov
Copy link
Contributor Author

rkirov commented Jan 12, 2017

@aluanhaddad note the return type of r means the second overload was chosen. Also this used to work in 2.0.x, any idea what changed?

@aluanhaddad
Copy link
Contributor

aluanhaddad commented Jan 12, 2017

note the return type of r means the second overload was chosen

I'm not sure what you mean, the correct overload is chosen if ordered as shown

declare function it(f: (x: string) => void): string;
declare function it(f: () => void): number;

let r = it((x) => {x}); // string

Also this used to work in 2.0.x, any idea what changed?

I believe must have been the result of a bug being fixed as this behavior is intentional, see #10645 (comment).

@rkirov
Copy link
Contributor Author

rkirov commented May 10, 2017

I meant is that if you go -

http://www.typescriptlang.org/play/#src=declare%20function%20it(f%3A%20()%20%3D%3E%20void)%3A%20number%3B%0Adeclare%20function%20it(f%3A%20(x%3A%20string)%20%3D%3E%20void)%3A%20string%3B%0A%0Alet%20r%20%3D%20it((x)%20%3D%3E%20%7Bx%7D)%3B

and hover over r you see it is string, while if you hover over x- it is any.

I find that surprising, as if TS choose the first overload for the callback body, but the second for the return type. But maybe my mental model is off.

@RyanCavanaugh RyanCavanaugh added the Needs Investigation This issue needs a team member to investigate its status. label May 24, 2017
@mhegazy
Copy link
Contributor

mhegazy commented Feb 8, 2018

This should be now flagged as an implicit any under --noImplicitAny. This is really a side effect of how the compiler does overload resolution with respect to context sensitive lambdas. Overloads are tried in order, and context sensitive lambdas need a contextual type, the compiler will apply the one from the first overload, but once that happens it can not un-apply it, since contextual types have implications on the rest of the expressions inside the function.

@mhegazy mhegazy added Design Limitation Constraints of the existing architecture prevent this from being fixed and removed Needs Investigation This issue needs a team member to investigate its status. labels Feb 8, 2018
@typescript-bot
Copy link
Collaborator

Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.

@microsoft microsoft locked and limited conversation to collaborators Jul 3, 2018
@typescript-bot typescript-bot added the Fix Available A PR has been opened for this issue label Feb 15, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed Fix Available A PR has been opened for this issue
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants