What's the difference between 'extends' and 'implements' in TypeScript

Short version

  • extends means:

The new class is a child. It gets benefits coming with inheritance. It has all properties, methods as its parent. It can override some of these and implement new, but the parent stuff is already included.

  • implements means:

The new class can be treated as the same "shape", while it is not a child. It could be passed to any method where the Person is required, regardless of having different parent than Person

More ...

In OOP (languages like C#, Java) we would use

extends to profit from inheritance (see wiki). Small cite:

... Inheritance in most class-based object-oriented languages is a mechanism in which one object acquires all the properties and behaviours of the parent object. Inheritance allows programmers to: create classes that are built upon existing classes ...

implements will be more for polymorphism (see wiki). Small cite:

... polymorphism is the provision of a single interface to entities of different types...

So, we can have really different inheritance tree of our class Man.

class Man extends Human ...

but if we also declare that we can pretend to be a different type - Person:

class Man extends Human 
          implements Person ...

.. then we can use it anywhere, where the Person is required. We just have to fulfill Persons's "interface" (i.e. implement all its public stuff).

implement other class? That is really cool stuff

Javascript's nice face (one of the benefits) is the built-in support of the Duck typing (see wiki). Small cite:

"If it walks like a duck and it quacks like a duck, then it must be a duck."

So, in Javascript, if two different objects... would have one similar method (e.g. render()) they can be passed to a function which expects it:

function(engine){
  engine.render() // any type implementing render() can be passed
}

To not lose that - we can in Typescript do the same - with more typed support. And that is where

class implements class

has its role, where it makes sense

In OOP languages as C# ... no way to do that...

Also The documentation should help here:

Interfaces Extending Classes

When an interface type extends a class type it inherits the members of the class but not their implementations. It is as if the interface had declared all of the members of the class without providing an implementation. Interfaces inherit even the private and protected members of a base class. This means that when you create an interface that extends a class with private or protected members, that interface type can only be implemented by that class or a subclass of it.

This is useful when you have a large inheritance hierarchy, but want to specify that your code works with only subclasses that have certain properties. The subclasses don’t have to be related besides inheriting from the base class. For example:

class Control {
    private state: any;
}

interface SelectableControl extends Control {
    select(): void;
}

class Button extends Control implements SelectableControl {
    select() { }
}

class TextBox extends Control {
    select() { }
}

// Error: Property 'state' is missing in type 'Image'.
class Image implements SelectableControl {
    private state: any;
    select() { }
}

class Location {

}

So, while

  • extends means - it gets all from its parent
  • implements in this case is almost like implementing an interface. Child object can pretend that it is parent... but it does not get any implementation

In typescript (and some other OO languages) you have classes and interfaces.

An interface has no implementation, it's just a "contract" of what members/method this type has.
For example:

interface Point {
    x: number;
    y: number;
    distance(other: Point): number;
}

Instances who implement this Point interface must have two members of type number: x and y, and one method distance which receives another Point instance and returns a number.
The interface doesn't implement any of those.

Classes are the implementations:

class PointImplementation implements Point {
    public x: number;
    public y: number;

    constructor(x: number, y: number) {
        this.x = x;
        this.y = y;
    }

    public distance(other: Point): number {
        return Math.sqrt(Math.pow(this.x - other.x, 2) + Math.pow(this.y - other.y, 2));
    }
}

(code in playground)

In your example you treat your Person class once as a class when you extend it and once as an interface when you implement it.
Your code:

class Person {
    name: string;
    age: number;
}
class Child  extends Person {}

class Man implements Person {}

Has a compilation error saying:

Class 'Man' incorrectly implements interface 'Person'.
Property 'name' is missing in type 'Man'.

And that's because interfaces lack implementation.
So if you implement a class then you only take its "contract" without the implementation, so you'll need to do this:

class NoErrorMan implements Person {
    name: string;
    age: number;
}

(code in playground)

Bottom line is that in most cases you want to extend another class and not to implement it.


Extends VS implements

  • extends: The child class (which is extended) will inherit all the properties and methods of the class is extends
  • implements: The class which uses the implements keyword will need to implement all the properties and methods of the class which it implements

To put in simpler terms:

  • extends: Here you get all these methods/properties from the parent class so you don't have to implement this yourself
  • implements: Here is a contract which the class has to follow. The class has to implement at least the following methods/properties

Example:

class Person {
  name: string;
  age: number;

  walk(): void {
    console.log('Walking (person Class)')
  }

  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
}
class child extends Person { }

// Man has to implements at least all the properties
// and methods of the Person class
class man implements Person {
  name: string;
  age: number

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

  walk(): void {
    console.log('Walking (man class)')
  }

}

(new child('Mike', 12)).walk();
// logs: Walking(person Class)

(new man('Tom', 12)).walk();
// logs: Walking(man class)

In the example we can observe that the child class inherits everything from Person whereas the man class has to implement everything from Person itself.

If we were to remove something from the man class for example the walk method we would get the following compile time error:

Class 'man' incorrectly implements class 'Person'. Did you mean to extend 'Person' and inherit its members as a subclass? Property 'walk' is missing in type 'man' but required in type 'Person'.(2720)