Typescript interfaces

Interfaces (within Typescript) are used in a variety of ways.

Defining expectations/restrictions

We can define an interface such as IPoint

interface IPoint {
    x: number;
    y: number;
}

Just like other languages, we can then implement this interface and we’re required to duplicate the properties or methods declared on it.

For example here’s an implementation

class Point implements IPoint {
    constructor(public x: number, public y: number) {        
    }
}

We’ve used public constructor parameters hence implementing the IPoint interface.

Now we can create an instance of the Point like this

// p is a Point
var p = new Point(2, 3);
// p is declared as an IPoint
var p: IPoint = new Point(2, 3);

Within TypeScript an interface can also simply be thought of as shaping our data, so in this example we could create an anonymous class of type IPoint like this

var p: IPoint = {x : 2, y: 4};

We can also declare an instance of an anonymous type like this

var p = {x : 2, y: 4};

Typescript supports “duck typing” so we can create functions such as

function output(p: IPoint) {
   //
}

and we can pass a type which implements an IPoint or a duck typed anonymous type, for example

output({x : 2, y: 4});

Because of duck typing we do have an issue whereby the following two interfaces are structurally equivalent

interface IPoint {
    x: number;
    y: number;
}

interface I2d {
    x: number;
    y: number;
}

and hence this will compile and run

var i2d: I2d = {x : 2, y: 4};
var p: IPoint = i2d;

In such a case, the interfaces have the same properties and names and are structurally equivalent.

Things get a little more interesting with interfaces and anonymous types, in that we can write something like this

function whatIsThis() {
    return {x:2};
}

Obviously it’s not an IPoint or I2d, but it could be. In this example it’d create an anonymous type but we could cast the type like this, but this will fail to compile due to the missing y property.

function whatIsThis() {
    return <IPoint>{x:2};
}

Empty interfaces

We can also define empty interfaces, such as

interface IEmpty {}

function output(e: IEmpty) {
    console.log(e);
}

output("Hello World");

In this case this is equivalent to an any and hence does not cause a compile time error and output will display “Hello World”.

Type erasure

Interfaces within Typescript are erased at compile/transpile time, hence whilst they aid in ensuring our types are as expected, once compiled to JavaScript they’re removed.

Hence no runtime type checking exists for such types.