Skip to main content
Version: 1.10.0

Interfaces

An interface is a list of types and values that you can apply to a namespace. When you apply an interface to a namespace, that namespace must have all of the types and values in the interface. The namespace can also have additional definitions that are not in the interface. The LIGO compiler warns you of any mismatches between the interface and the namespace.

For example, the following interface specifies that a namespace must have these contents:

  • A type named t, although the data type of that type is not specified, which makes it an abstract type
  • A function named add, which accepts two values of type t and returns a value of type t
  • Values one and two, which are of the type t
interface Euro_INTF {
type t;
const add: (a: t, b: t) => t;
const one: t;
const two: t;
};

To apply an interface to a namespace, put the name of the interface after the keyword implements and the namespace name, as in the following example. It's said that the namespace implements the interface. This namespace defines the type t as a nat and defines the add function and the one and two values. It also adds a function named multiply that is not specified in the interface:

namespace Euro implements Euro_INTF {
export type t = nat; // No more abstract
export const add = (a: t, b: t): t => a + b;
export const one: t = 1n;
export const two: t = 2n;
export const multiply = (a: t, b: t): t=> a * b;
};

The namespace must instantiate any abstract type in the interface, as this namespace defines the abstract type t as a nat.

Extending interfaces

Interfaces can be extended by inheritance with the extends keyword, as in this example:

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 that the type t remains abstract in all of the interfaces. Namespaces that use any of these interfaces must instantiate the type.

Interfaces can extend more than one interface, which can lead to an interface that extends a base interface more than once, known as diamond inheritance. For example, the following interface extends two interfaces from the previous example. Because both of these interfaces extend the same base interface, it is as if the interface extends the base interface twice. Diamond inheritance doesn't cause any problems for the interface.

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

Interfaces can have optional types and values indicated with a question mark ?. In the previous example, the interface NewEuro_INTF has an optional value five_hundred. This namespace defines this optional value and adds a value named twenty that is not defined in the NewEuro_INTF interface:

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
}