Skip to content

Overload conflicts make implementation impossible #4786

Closed

Description

@omidkrad

I created type definitions for Aurelia Event Aggregator as below. It compiles fine.

interface Constructor<T> {
    new (...args: any[]): T;
}

declare class EventAggregator
{
    subscribe(event: string, callback: (message: any) => void): void;
    subscribe<T>(event: Constructor<T>, callback: (message: T) => void): void;

    publish(event: string, data?: any): void;
    publish<T>(event: T): void;
}

class SomeMessage {
    constructor(public data: string) {}
}

var ea = new EventAggregator();

// event is string, message is any
ea.subscribe("myEvent", message => {
    console.log(message.anything);
});

// event is class constructor, message is instance of class
ea.subscribe(SomeMessage, message => {
    console.log(message.data);
});

// event is string, message is any 
ea.publish("myEvent", { anything: 1 });

// event is class instance
ea.publish(new SomeMessage(""));

Even though it is possible to define declarations for this class, it is impossible to implement it in TypeScript. The following produces errors, and I can't figure how to fix it.

interface Constructor<T> {
    new (...args: any[]): T;
}

class EventAggregator
{
    subscribe(event: string, callback: (message: any) => void): void;
    subscribe<T>(event: Constructor<T>, callback: (message: T) => void): void {
    }

    publish(event: string, data?: any): void;
    publish<T>(event: T): void {
    }
}

class SomeMessage {
    constructor(public data: string) {}
}

var ea = new EventAggregator();

// event is string, message is any
ea.subscribe("myEvent", message => {
    console.log(message.anything);
});

// event is class constructor, message is instance of class
ea.subscribe(SomeMessage, message => {
    console.log(message.data);
});

// event is string, message is any 
ea.publish("myEvent", { anything: 1 });

// event is class instance
ea.publish(new SomeMessage(""));

Is this a bug?

Here's the original JS source (ES6) for reference: aurelia/event-aggregator

Activity

  1. changed the title [-]Overload conflicts[/-] [+]Overload conflicts make implementation impossible[/+] on Sep 14, 2015
  2. mhegazy commented on Sep 14, 2015

    @mhegazy
    Contributor

    method definition is not counted as part of the overload set. you need to 1. define an overload signature of each overload, and 2. have an implementation signature that is compatible with all the overloads.

    class EventAggregator {
        subscribe(event: string, callback: (message: any) => void): void;
        subscribe<T>(event: Constructor<T>, callback: (message: T) => void): void;
        subscribe(event: string|Constructor<any>, callback: (message: any) => void): void {
    
        }
    
        publish(event: string, data?: any): void;
        publish<T>(event: T): void;
        publish(event:any): void {
        }
    }
  3. danquirk commented on Sep 14, 2015

    @danquirk
    Member

    This is a common source of confusion. Can we improve the error here? If the assignability check fails could we then check assignability against the implementation signature to include more helpful error text (or have we already thrown away that context by then)? That might help people solve the issue without having to go from the IDE to StackOverflow/GitHub/etc.

  4. omidkrad commented on Sep 14, 2015

    @omidkrad
    Author

    Mohamed Hegazy (@mhegazy) that worked. Thanks.

    Is there any way to say that a parameter can take only object instances and not class constructors, so that for example ea.publish(SomeMessage) is not allowed?

  5. danquirk commented on Sep 14, 2015

    @danquirk
    Member

    A hacky option:

    interface NotFunction {
        length?: void;
    }
    
    class EventAggregator {
        publish(event: string, data?: any): void;
        publish<T extends NotFunction>(event: T): void;
        publish(event:any): void { }
    }
    
    var e: EventAggregator;
    e.publish(EventAggregator); // error
    e.publish(1); // ok
    e.publish(''); // ok
    e.publish(new EventAggregator()); // ok
  6. omidkrad commented on Sep 15, 2015

    @omidkrad
    Author

    Thank you very much. I'm closing this question. You may want to open a separate issue for improving the error message for this case.

  7. locked and limited conversation to collaborators on Jun 19, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    QuestionAn issue which isn't directly actionable in code

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions