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

Order of method overloading declaration matters when one parameter type extends the other #1860

Closed
hraban opened this issue Jan 30, 2015 · 2 comments
Labels
By Design Deprecated - use "Working as Intended" or "Design Limitation" instead

Comments

@hraban
Copy link

hraban commented Jan 30, 2015

Playing around with the type definitions for React 0.13 I ran into this problem:

declare module Test {
    interface Parent {
        y: number;
    }
    interface Child extends Parent {
        z: string;
    }

    interface ParentDeriv {
        yderiv: number;
    }
    interface ChildDeriv extends ParentDeriv {
        zderiv: string;
    }

    interface Api {
        makeParent(): Parent;
        makeChild(): Child;
        meth(element: Parent): ParentDeriv;
        meth(element: Child): ChildDeriv;
    }

    var api: Api;
}

var x = Test.api.meth(Test.api.makeParent());
x.zderiv; // Should be: error. Is: error.
var y = Test.api.meth(Test.api.makeChild()); // takes wrong method.
y.zderiv; // Should be: ok. Is: error. y is inferred ParentDeriv.

But if you flip the method declarations around, it works fine:

declare module Test {
    interface Parent {
        y: number;
    }
    interface Child extends Parent {
        z: string;
    }

    interface ParentDeriv {
        yderiv: number;
    }
    interface ChildDeriv extends ParentDeriv {
        zderiv: string;
    }

    interface Api {
        makeParent(): Parent;
        makeChild(): Child;
        // Note order: child class first
        meth(element: Child): ChildDeriv;
        meth(element: Parent): ParentDeriv;
    }

    var api: Api;
}

var x = Test.api.meth(Test.api.makeParent());
x.zderiv; // Should be: error. Is: error.
var y = Test.api.meth(Test.api.makeChild());
y.zderiv; // Should be: ok. Is: ok.

This is a bug, right? With TS I'm never sure..

Tested with 1.4 (Playground and local)

@RyanCavanaugh RyanCavanaugh added the By Design Deprecated - use "Working as Intended" or "Design Limitation" instead label Jan 30, 2015
@RyanCavanaugh
Copy link
Member

Overload ordering absolutely matters. The rule is that the first applicable overload is chosen. We tried a bunch of other rules and this was the only one anyone could ever make sense of in practice.

This does mean that it's possible to write overloads which are "unreachable" by putting the general signature before the more specific overload; care needs to be taken to put the more-specific overloads first.

@hraban
Copy link
Author

hraban commented Jan 30, 2015

Alright thanks for getting back so quickly, sorry for the false alarm.

@microsoft microsoft locked and limited conversation to collaborators Jun 18, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
By Design Deprecated - use "Working as Intended" or "Design Limitation" instead
Projects
None yet
Development

No branches or pull requests

2 participants