Skip to content

[Function Overloading] implementation is obviously different to the signatures, but no ts error #54406

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
shhider opened this issue May 26, 2023 · 3 comments
Labels
Duplicate An existing issue was already created

Comments

@shhider
Copy link

shhider commented May 26, 2023

Bug Report

πŸ”Ž Search Terms

overload, implementation, signature, different, compatible

πŸ•— Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about This-FAQ

⏯ Playground Link

code in playground

πŸ’» Code

// signature
function foo(xx: number): number;
function foo(xx: number, yy: string): string;

// implementation
// ❗️it may return `boolean`, differing to the signatures
function foo(xx: number, yy?: string): number | string | boolean {
    if (yy == null) {
        return xx;
    }
    if (yy === "666") {
        return true;
    }
    return yy;
}

πŸ™ Actual behavior

Obviously, the implementation doesn't satisfy the signatures, but TS didn't "find" it. It confused me, and brought some issues into my project.

I don't know whether it is by-design or a bug, and I didn't find any doc about this behavior. Please tell me the reason of this design, if it is by-design.

πŸ™‚ Expected behavior

// signature
// EXPECTED: Tell me "This overload signature is not compatible with its implementation signature."
function foo(xx: number): number;
function foo(xx: number, yy: string): string;

// implementation
function foo(xx: number, yy?: string): number | string | boolean {
    // ...
}
@fatcerberus
Copy link

fatcerberus commented May 26, 2023

Overload checking is necessarily loose because it's pretty much impossible to constrain it in a way that makes it fully sound without overcomplicating the rules and getting in the way. For example, the same kind of unsoundness happens even with the "correct" signature:

// signature
function foo(xx: number): number;
function foo(xx: number, yy: string): string;

// implementation
function foo(xx: number, yy?: string): number | string {
    return 42;  // unconditionally returns a number
}

...namely that nothing prevents you from returning the wrong type for the overload that was actually called. There doesn't really seem to be an easily generalizable mechanism by which you could reject the case in the OP without also rejecting the "correct" signature, either, since both cases involve a return type which is simultaneously wider than both overloads'. So what would the rule for that be?

@jcalz
Copy link
Contributor

jcalz commented May 26, 2023

Duplicate #52478 and ultimately #13235

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label May 26, 2023
@microsoft-github-policy-service

This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

4 participants