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

Class inheritance with specialized method signatures #10229

Closed
Koloto opened this issue Aug 9, 2016 · 4 comments
Closed

Class inheritance with specialized method signatures #10229

Koloto opened this issue Aug 9, 2016 · 4 comments
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed

Comments

@Koloto
Copy link

Koloto commented Aug 9, 2016

I'm trying to use specialized signatures with string literal types to write typed events. Everything is good in single class or interface. But it doesn't work with inheritance.

Code to reproduce

class Observable {
    // subscribe to "change" event
    bind(eventName: "change", callback: (sender: this, args: ObservableChangeArgs) => void): this;
    // subscribe to other events
    bind(eventName: string, callback: Function): this;
    bind(eventName: string, callback: Function): this {
        // some implementation here
        return this;
    }
}

interface ObservableChangeArgs {
    prop?: string;
    value?: any;
}

class View extends Observable {
}

interface View extends Observable {
    // subscribe to "render" event
    bind(eventName: "render", callback: (sender: this, args: ViewRenderArgs) => void): this;
    // subscribe to other events
    bind(eventName: string, callback: Function, context?: any): this;
}

interface ViewRenderArgs {
    domElement: HTMLElement;
}

let view = new View();
view.bind("render", (sender, args) => {
    console.log(args.domElement.tagName); // Ok
}).bind("render", (sender, args) => {
    console.log(args.unknownProperty); // Error, this is expected
}).bind("change", (sender, args) => {
    console.log(args.prop); // Ok
}).bind("change", (sender, args) => {
    console.log(args.unknownProperty); // Also Ok, but error is expected
});

I expect an error in last callback because change event is defined in the parent class and unknownProperty is not declared there. I also tried overload bind method directly in View class or use just interfaces instead of classes. No luck:( A workaround is to copy all signatures from parent class to child. But this is not good way.

Reproduced in 1.8.10 and also in typescript@next 2.1.0-dev.20160809

@RyanCavanaugh RyanCavanaugh added the Design Limitation Constraints of the existing architecture prevent this from being fixed label Aug 9, 2016
@RyanCavanaugh
Copy link
Member

A workaround is to copy all signatures from parent class to child.

Unfortunately this is currently the only way to accomplish what you're trying to do. We've been trying to figure out how to "correctly" copy down signatures from one class to another but there is a lot of ambiguity in what the intent of signature merging is in many cases.

@Koloto
Copy link
Author

Koloto commented Aug 9, 2016

Any chances to see the solution in v2.1 or maybe 2.2?

@RyanCavanaugh
Copy link
Member

We tried for a long time to come up with a solution and couldn't. I can't predict when we'll get cleverer 😉

@thw0rted
Copy link

Hey, this can now be kinda-sorta automated with a bunch of derived-type magic. I used the code from this SO answer to make an interface mapping specialized signature literal values to the arguments that get passed to the rest of the function. This means that in your subclass, if you want to add more overloads, you just make an interface for the subclass's new events and inherit from the superclass's event interface.

It's a bunch of extra boilerplate but if you have a lot of subclasses adding specialization, it can save tons of repetition. (Thanks again, @dragomirtitian!)

@microsoft microsoft locked and limited conversation to collaborators Jul 31, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed
Projects
None yet
Development

No branches or pull requests

3 participants