Skip to main content
Version: Next

Extending

Unlike namespaces, interfaces can be extended by inheritance. The construct is introduced by the keyword extends, like so

interface Euro_INTF {
type t;
const add: (a: t, b: t) => t;
const one: t;
const two: t;
};
interface WithTenEuro_INTF extends Euro_INTF {
const ten: t;
};
interface WithFiftyEuro_INTF extends Euro_INTF {
const fifty: t;
};

Note how the type t remains abstract in WithTenEuro_INTF and WithFiftyEuro_INTF.

It is possible to design diamond inheritance, that is, inheriting twice the same base interface, like so:

interface NewEuro_INTF
extends WithTenEuro_INTF, WithFiftyEuro_INTF {
const hundred: t;
const five_hundred?: t;
};

Here, the abstract type t was inherited twice from Euro_INTF. Note the optional value five_hundred, distinghished as such by a question mark: five_hundred?. This means that a namespace implementing NewEuro_INTF can choose not to implement five_hundred (because it is often counterfeited). The implementation of an interface can be done as follows:

namespace NewEuro implements NewEuro_INTF {
export type t = int;
export const add = (a: t, b: t) => a + b;
export const one: t = 1;
export const two: t = 2;
export const ten: t = 10;
export const fifty: t = 50;
export const hundred: t = 100;
export const five_hundred: t = 500; // Could be omitted
const twenty: t = 20; // Extra new constant
}

Note how five_hundred was indeed implemented, although it was not mandatory, and how we added twenty, even it is not found in any of the inherited signatures.