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

Contextually type class property initializers by extends/implements types #3667

Closed
RyanCavanaugh opened this issue Jun 29, 2015 · 11 comments
Closed
Assignees
Labels
Committed The team has roadmapped this issue Design Limitation Constraints of the existing architecture prevent this from being fixed Suggestion An idea for TypeScript Won't Fix The severity and priority of this issue do not warrant the time or complexity needed to fix it

Comments

@RyanCavanaugh
Copy link
Member

When a property has exactly one type from an extends or implements clause, we should contextually type that property's initializer by the type from the clause. For example:

interface ThingListener {
    handleEvent: (x: MouseEvent) => void;
}

class Foo implements ThingListener {
    handleEvent = x => {
        // No error, but this code is incorrect
        console.log(x.timestamp);
    }
}

Ideally we could take this one step further when widening. The following behavior is also undesirable:

interface HasLength {
    length: number
}

class Foo implements HasLength {
    // length: any, not really what we intended
    length = undefined;
}

var x = new Foo();
x.length = 'wat'; // should not be allowed

e.g. #3666

@NoelAbrahams
Copy link

Is this not the same as #1373?

@RyanCavanaugh
Copy link
Member Author

#1373 is about methods, this is about properties

@DanielRosenwasser
Copy link
Member

So is this a broader proposal than #1373? In other words, in the following example, is the arrow function in SortByQueryId contextually typed?

Additionally, if we declared getvalue in ISortInfo as a property but defined it as a method in the class, would its parameter's type be inferred?

    export interface ISortInfo
    {
        getvalue(x: QuerySummary): number | string;
        order: SortDir;
        ordercalc?: number;
    }

    class SortByQueryId implements ISortInfo
    {
        getvalue = x => x.QueryId;
        order = SortDir.Flip;
    }

@RyanCavanaugh
Copy link
Member Author

I don't think we should distinguish between method-style and property-style declarations in the interface - both are an equally valid "source" in terms of type information, regardless of how the class is implementing it.

In the example, I would expect the arrow function to be contextually typed under this proposal, but not #1373.

@sophiajt
Copy link
Contributor

Agree with @NoelAbrahams - can we merge this with #1373? If this subsumes that proposal, can we dupe that one to this one?

@tinganho
Copy link
Contributor

Also merge with #3804 ? Then we include interfaces too.

@Gaelan
Copy link

Gaelan commented Sep 21, 2015

👍

@omidkrad
Copy link

omidkrad commented Oct 8, 2015

From #5181 the following sample reproduces this issue:

declare module Backbone {
    interface RoutesHash {
        [routePattern: string]: string | {(...urlParts: string[]): void};
    }
    class Events { }
    class Router extends Events {
        routes: RoutesHash;
    }
}

declare module Marionette {
    class AppRouter extends Backbone.Router {
    }
}

module Backbone.Tests {
    // Error, routes is not contextually typed
    class MyRouter extends Backbone.Router {
        routes = {
            "some/route": "someMethod",
            "some/otherRoute": () => {}
        };
    }
}

module Marionette.Tests {
    // Error, routes is not contextually typed
    class MyRouter extends Marionette.AppRouter {
        routes = {
            "some/route": "someMethod",
            "some/otherRoute": () => {}
        };
    }
}

@RyanCavanaugh RyanCavanaugh added the In Discussion Not yet reached consensus label Oct 8, 2015
@RyanCavanaugh RyanCavanaugh added Committed The team has roadmapped this issue and removed In Discussion Not yet reached consensus labels Nov 3, 2015
@RyanCavanaugh
Copy link
Member Author

Tentatively approved -- this would be a slight breaking change, but probably very much in the "good" direction (i.e. uncovers bugs that were going missed before). We will investigate breakages in our RWC suite to see what the net impact is.

@omidkrad
Copy link

omidkrad commented Nov 6, 2015

I'd be fine with this breaking change.

@sandersn
Copy link
Member

sandersn commented May 6, 2016

Unfortunately, we couldn't come up with a solution that was both consistent and backward-compatible. The breaks in our Real World Code suite were more bad than good. See #6118 for details. I'm closing this for now.

@sandersn sandersn closed this as completed May 6, 2016
@sandersn sandersn added Design Limitation Constraints of the existing architecture prevent this from being fixed Won't Fix The severity and priority of this issue do not warrant the time or complexity needed to fix it labels May 6, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Committed The team has roadmapped this issue Design Limitation Constraints of the existing architecture prevent this from being fixed Suggestion An idea for TypeScript Won't Fix The severity and priority of this issue do not warrant the time or complexity needed to fix it
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants