Skip to content

Interfaces

Video Lecture

Section Video Links
Interfaces Interfaces Interfaces 

Overview

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.

To make sure that a class definition fully complies with the rules in your chosen Interface, we use the implements keyword.

In the first example below, we try to create a class that must implement a particular interface. The interface can describe any types that you wish, but for example may have been decided by some business rules or any other important reason. When creating the class below, the IDE and TSC have detected that the class does not fully comply.

Implementing TypeScript interfaces is an optional safety net that can be used to ensure consistency and correctness throughout your code base.

Interface Example 1

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
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 was indicated in the IAnimal interface.

Interface Example 2

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
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. For the Cat class to be correct, it should have implemented the feed method as described in its chosen interface.

Also, note that in the interface declaration, the feed method does not have a method body. Interface methods don't contain method bodies, just the method signature only. The implementation of the method 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 for more information about public.

Interface Example 3

Below is a working example of the code where there are two classes named Cat and Dog that both correctly fully implement the IAnimal interface. I.e., they both implement the name and age properties, and also implement the feed method accepting attributes with the correct types.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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 let's inspect the compiled JavaScript in ./dist/test.js.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
'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. They are useful for ensuring that code complies to chosen rules when developing a project.