Skip to content

Interfaces

Interfaces in TypeScript are a useful tool that you can use for your classes to ensure that they conform to any specific rules that you want them to. This is especially useful if there are many people working on the same code base, and any classes need to follow any specific rules.

Interface Example 1

interface IAnimal {
    name: string
    age: number
}

class Cat implements IAnimal {
    name: string

    constructor(name: string) {
        this.name = name
    }
}

If you were to copy this above code into ./src/test.ts, both TSC and the VSCode IDE would indicate an error

Class 'Cat' incorrectly implements interface 'IAnimal'.
Property 'age' is missing in type 'Cat' but required in type 'IAnimal'

Since the Cat class implements IAnimal, it also needs to declare the age property as indicated in the IAnimal interface.

Interface Example 2

Note that interface rules can also be applied to class methods.

interface IAnimal {
    name: string
    age: number

    feed(food: string, amount: number): void
}

class Cat implements IAnimal {
    name: string
    age: number

    constructor(name: string, age: number) {
        this.name = name
        this.age = age
    }
}

If you were to replace the code in ./src/test.ts with the above code. The error would now indicate that the feed method was not implemented in the Cat class.

Note that in the interface declaration, the feed method does not have a method body. Interface methods are kept empty, and the implementation is instead written in the class that will implement the interface.

An interface is essentially a public contract that all classes that implement it must follow. See Access Modifiers from more information about public.

Interface Example 3

Below is a working example of the code where two classes Cat and Dog both implement the IAnimal interface.

interface IAnimal {
    name: string
    age: number

    feed(food: string, amount: number): void
}

class Cat implements IAnimal {
    name: string
    age: number

    constructor(name: string, age: number) {
        this.name = name
        this.age = age
    }

    feed(food: string, amount: number): void {
        console.log(
            'Feeding ' +
                this.name +
                ' the Cat ' +
                amount +
                ' kg of ' +
                food
        )
    }
}

class Dog implements IAnimal {
    name: string
    age: number

    constructor(name: string, age: number) {
        this.name = name
        this.age = age
    }

    feed(food: string, amount: number): void {
        console.log(
            'Feeding ' +
                this.name +
                ' the Dog ' +
                amount +
                ' kg of ' +
                food
        )
    }
}

const CAT = new Cat('Cosmo', 8)
const DOG = new Dog('Rusty', 12)
CAT.feed('Fish', 0.1)
DOG.feed('Beef', 0.25)

Re compile and execute,

tsc -p ./src
node ./dist/test.js

Outputs

Feeding Cosmo the Cat, 0.1kg of Fish
Feeding Rusty the Dog, 0.25kg of Beef

Now lets inspect the compiled JavaScript in ./dist/test.js.

'use strict'
class Cat {
    constructor(name, age) {
        this.name = name
        this.age = age
    }
    feed(food, amount) {
        console.log(
            'Feeding ' +
                this.name +
                ' the Cat ' +
                amount +
                ' kg of ' +
                food
        )
    }
}
class Dog {
    constructor(name, age) {
        this.name = name
        this.age = age
    }
    feed(food, amount) {
        console.log(
            'Feeding ' +
                this.name +
                ' the Dog ' +
                amount +
                ' kg of ' +
                food
        )
    }
}
const CAT = new Cat('Cosmo', 8)
const DOG = new Dog('Rusty', 12)
CAT.feed('Fish', 0.1)
DOG.feed('Beef', 0.25)

Note that there is no indication of any interfaces in the compiled code. Interfaces are a TypeScript concept and are not used or enforced in JavaScript.