Skip to content

Overloading function fails with union types #29969

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
burtek opened this issue Feb 19, 2019 · 4 comments
Closed

Overloading function fails with union types #29969

burtek opened this issue Feb 19, 2019 · 4 comments

Comments

@burtek
Copy link

burtek commented Feb 19, 2019

// @strictNullChecks: true

interface Data {
    data: any
}

declare const value: Data | undefined;

function doSthWithValue(v: undefined): undefined;
function doSthWithValue(v: Data): Data;
function doSthWithValue(v?: Data) {
    return v;
}

const a = doSthWithValue(value); // <-- error

EDIT: see comment below, it is not connected to strictNullChecks

Expected behavior:

Should not throw error with strictNullChecks enabled

Actual behavior:

It throws error:

Argument of type 'Data | undefined' is not assignable to parameter of type 'undefined'.
  Type 'Data' is not assignable to type 'undefined'.

Playground Link:

Enable strictNullChecks. The order of overloaded signatures does not change anything

https://www.typescriptlang.org/play/#src=interface%20Data%20%7B%0D%0A%20%20%20%20data%3A%20any%0D%0A%7D%0D%0A%0D%0Adeclare%20const%20value%3A%20Data%20%7C%20undefined%3B%0D%0A%0D%0Afunction%20doSthWithValue(v%3A%20undefined)%3A%20undefined%3B%0D%0Afunction%20doSthWithValue(v%3A%20Data)%3A%20Data%3B%0D%0Afunction%20doSthWithValue(v%3F%3A%20Data)%20%7B%0D%0A%20%20%20%20return%20v%3B%0D%0A%7D%0D%0A%0D%0Aconst%20a%20%3D%20doSthWithValue(value)%3B%0D%0A

Related issues:
#14107

@jack-williams
Copy link
Collaborator

This isn't actually related to strict null checks, but related to overload resolution. Here is the same problem without optionality and undefined.

declare const value: "L" | "R";

function doSthWithValue(v: "L"): "L";
function doSthWithValue(v: "R"): "R";
function doSthWithValue(v: "L" | "R") {
    return v;
}

// Argument of type '"L" | "R"' is not assignable to parameter of type '"R"'.
const a = doSthWithValue(value);

I think the current situation is that TypeScript looks to prune overloads by only looking at the overloads that match the input type. If no overload individually matches then you get a type error. Basically, TypeScript is missing the following distributive rule for intersection types:

(A -> C) & (B -> C) <: (A | B) -> C

@burtek
Copy link
Author

burtek commented Feb 19, 2019

For some reason it worked when disabling strictNullChecks, so I thought it might be the issue. But your's example fails also without enabling it. Still a bug, I guess...?

Should I change the name of the issue? To what?

@jack-williams
Copy link
Collaborator

Managed to track down what looks to be the canonical issue for this problem: #14107.

@burtek burtek changed the title strictNullChecks break function overloading when param is possibly undefined Overloading function fails with union types Feb 19, 2019
@burtek
Copy link
Author

burtek commented Feb 19, 2019

For my case the following is enough:

function doSthWithValue(v: Data): Data;
- function doSthWithValue(v: undefined): undefined;
+ function doSthWithValue(v: Data | undefined): Data | undefined;
function doSthWithValue(v?: Data) {
    return v;
}

Yet the issue is still current. Closing in favour of #14107 with hope for getting it fixed soon

@burtek burtek closed this as completed Feb 19, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants