Description
openedon Aug 13, 2015
An alternative to extends
that is mostly identical but with the following variation: instead of erroring when properties are re-declared with different types, it would resolve to the type unions instead (properties having a function type are already overloaded in inheritance, so there's no need to address them):
interface A {
x: boolean;
}
interface B extends A { // Error! Incorrectly extends A. Types of x are incompatible.
x: number;
}
interface C overloads A { // OK! x is now of type boolean | number
x: number;
}
interface D overloads A { // OK! x is now of type boolean | number | string
x: number | string;
}
interface E overloads A { // OK! x is now of type boolean | (param: number): string
x(param: number): string;
}
An operator based on this variation of inheritance would have the property that for any two (object or function) interfaces A
, B
, A overload B
(illustrative, not suggested, name) can never fail, even if the operands contain incompatible property types (note: this assumes cycles are ignored in the operator version). In contrast to intersection, it wouldn't even fail if A
is an object type and B
is a function type, as hybrid object/function types are already allowed by standard inheritance.
This an attempt to address the challenge presented by @ahejlsberg of having an inheritance-like operation that is guaranteed not to fail when applied to generic type parameters:
declare function combine<T, U>(obj1: T, obj2: U): T overload U;
and thus may be used as a replacement to intersection that would be more consistent with the rest of the language (and inheritance logic in particular).
Even though I'm not a computer scientist or a language expert I tried to do my best for giving a basic direction (that is, at least a possible idea) on how to solve this. I'm not in a position to be able to see all the details, nuances or problems for integrating something like this into the language.