Skip to content

Functions union type or interface won't infer the correct argument types #39692

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
pikax opened this issue Jul 21, 2020 · 3 comments
Closed

Functions union type or interface won't infer the correct argument types #39692

pikax opened this issue Jul 21, 2020 · 3 comments
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed

Comments

@pikax
Copy link

pikax commented Jul 21, 2020

TypeScript Version: 3.9.x && 4.0.0.beta

Search Terms: function overload type interface union

Code

// function overload
function nav(x: (to: string, from1: string, next: number) => void): void;
function nav(x: (to: string, from1: string) => void): void;
function nav(x: any): any {
    return true;
}

nav((to, from, nex) => { }) // works
nav((to, from) => { }) // works


// using types

export type NavType =
    | ((to: string, from1: string, next: number) => void)
    | ((to: string, from1: string) => void)

const t1: NavType = (to, from, next) => { }; // works
const t2: NavType = (to, from) => { }; // doesn't work


// using interface with overloads
interface InterfaceType {
    (to: string, from1: string, next: number): void
    (to: string, from1: string): void
}

const i1: InterfaceType = (to, from, next) => { }; // works
const i2: InterfaceType = (to, from) => { }; // doesn't work

Expected behavior:
The argument inference should be the same when using type/interface or the function overload.

Actual behavior:
Union type fails to infer the 2 argument function
Interface fails to infer the overloads, if we comment one of the overloads it will correctly infer 1 or both.

Playground Link:
https://www.staging-typescript.org/play?ts=4.0.0-beta#code/PTAEDMFcDsGMBcCWB7apkDcCmAnANsgIYAmAUFHEqqNIRgBQAeAXKPfMqwM7w6LQBzADQQcyALYBGbr37CaWRvFbRI4gEa4AlKAC8APlAZkiYltbHTAbnIwEKNLQYs2HGX0EjwYqe7k6DIxMzC2CbCntqJyZWQmgAT3NQOPjQAG9SUCzQHCx4SBw0XkgsGwBfUlJo9mQvHxFoRQDDNNAynRBQAHdkHABrLiq6ehq6iWb0to6wHv7Bys7ILjlQeHiAByx5xXXe+FWNrFAAOToAFUO9TOyAHzYav09RCWlQHg95RqUVNU0cCcsZmuWTuIzcb1kT28L0eAgBwS0lVgqB4q1epwwF02elctWe4gaingE1aZSsoE6swGpGR0FR8AATKwMVijrpcWNxCS2uTOsRkFtoAByfZUyqkRbLQSgfjwXDgQiwI5dRDwAAW6Gw+CIxEGsvliqOAEloHKcAqlaz0sDcbDOa93nJCd8aL9tKFTDaHhCPvbYUlAaQKjSUftEK8TWaLVgrezRvjncS9C0eRSZr1qbTUYgmaBIwbLZc4xxOdyyWnQPzBSLuhnxZ0ABIAQQAwgBpVi8eIrDigIk4RX7dVHdaEAfiPK4GXQcDIfGrNXKjMrCJUNCYXAEEikNbYgCiSgHCAAYnY1wAeM59pRYaC60CnygOQzsq9E2-3kbgVj8cBTgAKEwpDoAD8oD-qAKhYFqNg7HsBzYgAypAo44gevCDo+kTQOeu5YMg4A0HQ+g2KQxBYLAeBjkcq4OERGAMvQ0CsMho4BmEQwMWCeLQgSCiMGW0yVgKXCmrW-ScYx8a8YJFZUvM4pAA

Related Issues:

@RyanCavanaugh RyanCavanaugh added the Design Limitation Constraints of the existing architecture prevent this from being fixed label Jul 21, 2020
@RyanCavanaugh
Copy link
Member

There's no reason to write overloads like this if you're intending to accept a callback; just take the 3-argument version.

In the cases where you can't just take the 3 argument version, the problem becomes apparent - TS would have to typecheck every possible way the callback might get called, which would open the door to a combinatorial explosion.

The overloaded version nav will just always take the top overload that matches, which isn't the case for union types or assignments.

@posva
Copy link

posva commented Jul 21, 2020

What about they return different values:

// using interface with overloads
interface InterfaceType {
    (to: string, from: string, next: () => void): void
    (to: string, from: string): Promise<void>
}

type Fn1 = (to: string, from: string...

Playground Link

Or maybe this still falls in the combinatorial explosion you mentioned

@posva
Copy link

posva commented Jun 2, 2021

@RyanCavanaugh but it does make sense if the return types are different

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed
Projects
None yet
Development

No branches or pull requests

3 participants