Skip to content

Why must two methods with the same name be identical when inheriting them from different interfaces? #2871

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
benjamin-hg opened this issue Apr 22, 2015 · 4 comments
Labels
By Design Deprecated - use "Working as Intended" or "Design Limitation" instead

Comments

@benjamin-hg
Copy link

declare class Super {
    set(property:string, value:any);
}

declare class SubA extends Super {
    set(property:"name", value:string);
    set(property:string, value:any); // don't know why this is needed, as it should be inherited
}

declare class SubB extends Super {
    set(property:"size", value:number);
    set(property:string, value:any); // okay, I repeat myself.
}


interface Both extends SubA, SubB {

}

Gives me:
Error:(16, 15) TS2320: Interface 'Both' cannot simultaneously extend types 'SubA' and 'SubB'.
Named properties 'set' of types 'SubA' and 'SubB' are not identical.

I'm working with Dojo, where SubA and SubB are two Widgets and Both is the type of a mixin.

Ironically, this prevents the error:

interface Both extends SubA, SubB {
    set(property:string, value:any); 
}
@RyanCavanaugh RyanCavanaugh added the By Design Deprecated - use "Working as Intended" or "Design Limitation" instead label Apr 22, 2015
@RyanCavanaugh
Copy link
Member

If they're not identical, we don't have any good way to "merge" them in an order that's predictable and meaningful. The workaround you posted is the intended one -- when two inherited properties aren't identical, the fix is to specify how they should be merged.

@benjamin-hg
Copy link
Author

@RyanCavanaugh Can you give an example, why merging declarations in this case can't be done in a predictable and meaningful way? Where is the conceptual difference to the merging described here: https://github.com/Microsoft/TypeScript/wiki/Declaration-Merging#merging-interfaces ?

@benjamin-hg
Copy link
Author

Or maybe, my question could be boiled down to: "Where can I find explained the difference between two interfaces with the same name getting merged and one interface extending two interfaces at a time"

[EDIT]:
Got kind of an answer in the spec, section 3.8.2.4: "Specialized Signatures":

When writing overloaded declarations such as the one above it is important to list the non-specialized signature last. This is because overload resolution (section 4.12.1) processes the candidates in declaration order and picks the first one that matches.

Every specialized call or construct signature in an object type must be assignable to at least one non-specialized call or construct signature in the same object type

So when merging interfaces with the same name, only the first must (and should) contain the non-specialized call signature. The merging then takes place in the reverse order, putting the members of last declared interface first.

In contrast, when merging interface members by extending two different interfaces at a time, both of them already must contain a non-specialized call signature for their specialized signatures.

In this case, the simple rule of putting the members of the latter before the members of the first will not be satisfactory, as every specialized call signature that come after a matching non-specialized call signature will be ignored.

That leads me to the following feature request:
Extend the rules for merging type members in case of extends as follows:
Merge interfaces like they had the same name. Afterwards, got through the merged member list from the last to the first. Remove all call signature declarations that are equivalent in both name and type.
At least in simple cases, like in my example above, this should yield the expected result.
Maybe there are some edge cases that still need to yield an error or that need the mentioned workaround.

@ip
Copy link

ip commented Sep 19, 2017

@RyanCavanaugh

If they're not identical, we don't have any good way to "merge" them in an order that's predictable and meaningful.

Last one wins, maybe?

I would understand why this error is popping if there are conflicts between merged interfaces, but it's there even when they're not.

@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

3 participants