Back to Course

Learn TypeScript

0% Complete
0/0 Steps
Lesson 9 of 25
In Progress

Defining Interfaces and Implementing Them in Classes

Welcome to the “Defining Interfaces and Implementing Them in Classes in TypeScript” section of our course “Learn TypeScript”! In this article, we will cover how to define interfaces and implement them in classes in TypeScript, and how you can use them to write more structured and reusable code. By the end of this article, you should have a good understanding of these concepts and be able to use them effectively in your TypeScript programs.

Introduction to Interfaces

Interfaces in TypeScript are used to describe the shape of an object. They define a set of properties and methods that an object should have, but do not provide any implementation for those properties and methods. For example:

interface Point {
  x: number;
  y: number;
  distanceToOrigin(): number;
}

In this example, we have defined an interface called “Point” that has two properties, “x” and “y”, and one method, “distanceToOrigin”. The interface specifies that an object that implements this interface must have these properties and method, but does not specify how they should be implemented.

To use an interface, you can create a class or object that implements it. For example:

class CartesianPoint implements Point {
  x: number;
  y: number;

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

  distanceToOrigin() {
    return Math.sqrt(this.x * this.x + this.y * this.y);
  }
}

In this example, we have defined a class called “CartesianPoint” that implements the “Point” interface. The class defines the properties and method specified in the interface and provides an implementation for them.

Implementing Multiple Interfaces

A class or object can implement multiple interfaces in TypeScript by separating them with a comma. For example:

interface Shape {
  area(): number;
}

interface Solid {
  volume(): number;
}

class Cube implements Shape, Solid {
  width: number;
  height: number;
  depth: number;

  constructor(width: number, height: number, depth: number) {
    this.width = width;
    this.height = height;
    this.depth = depth;
  }

  area() {
    return this.width * this.height * 6;
  }

  volume() {
    return this.width * this.height * this.depth;
  }
}

In this example, we have defined two interfaces, “Shape” and “Solid”, and a class called “Cube” that implements both interfaces. The class defines the properties and methods specified in both interfaces and provides an implementation for them.

Extending Interfaces

Interfaces in TypeScript can extend other interfaces using the “extends” keyword. This allows you to define a new interface that includes all the members of the base interface, and can also add additional members of its own. For example:

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

interface ThreeDimensionalPoint extends Point {
  z: number;
}

In this example, we have defined an interface called “ThreeDimensionalPoint” that extends the “Point” interface. The “ThreeDimensionalPoint” interface includes all the members of the “Point” interface, as well as an additional member called “z”.

A class or object that implements the “ThreeDimensionalPoint” interface must implement all the members of both the “ThreeDimensionalPoint” and “Point” interfaces. For example:

class CartesianPoint implements ThreeDimensionalPoint {
  x: number;
  y: number;
  z: number;

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

In this example, we have defined a class called “CartesianPoint” that implements the “ThreeDimensionalPoint” interface. The class defines all the properties specified in the “ThreeDimensionalPoint” and “Point” interfaces.

Optional Members

Interfaces in TypeScript can have optional members, which can be marked with a “?” symbol. This means that an object that implements the interface does not have to include these optional members. For example:

interface Point {
  x: number;
  y: number;
  label?: string;
}

class CartesianPoint implements Point {
  x: number;
  y: number;

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

let point = new CartesianPoint(3, 4);
console.log(point.label); // Outputs: undefined

In this example, we have defined an interface called “Point” that has an optional member called “label”. The class “CartesianPoint” implements the “Point” interface, but does not include the “label” property. When we create an instance of the “CartesianPoint” class and try to access the “label” property, it returns “undefined”.

Readonly Members

Interfaces in TypeScript can have readonly members, which can be marked with the “readonly” keyword. This means that the value of these members can be set only once, either in the constructor or when the object is created. For example:

interface Point {
  readonly x: number;
  readonly y: number;
}

class CartesianPoint implements Point {
  readonly x: number;
  readonly y: number;

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

let point = new CartesianPoint(3, 4);
point.x = 5; // Error: Cannot assign to 'x' because it is a read-only property

In this example, we have defined an interface called “Point” that has two readonly members, “x” and “y”. The class “CartesianPoint” implements the “Point” interface and defines the readonly properties. When we try to change the value of the “x” property on the “point” object, we get an error because it is a readonly property.

Readonly properties are useful when you want to prevent the value of a property from being changed after it has been set. This can be helpful for maintaining the integrity of your data and avoiding unintended side effects.

Conclusion

In conclusion, this article has covered how to define interfaces and implement them in classes in TypeScript, and how you can use them to write more structured and reusable code. You should now have a good understanding of these concepts and be able to use them effectively in your TypeScript programs. In future sections of our course, we will cover more advanced topics, such as generics and decorators, and how to use them to write more powerful TypeScript code.

Exercises

To review these concepts, we will go through a series of exercises designed to test your understanding and apply what you have learned.

Can a class or object implement multiple interfaces in TypeScript?

Yes, a class or object can implement multiple interfaces in TypeScript by separating them with a comma. For example:

interface Shape {
  area(): number;
}

interface Solid {
  volume(): number;
}

class Cube implements Shape, Solid {
  // Cube implements Shape and Solid
}

Can interfaces extend other interfaces in TypeScript?

Yes, interfaces can extend other interfaces in TypeScript using the “extends” keyword. This allows you to define a new interface that includes all the members of the base interface, and can also add additional members of its own. For example:

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

interface ThreeDimensionalPoint extends Point {
  z: number;
}

How do you define an interface in TypeScript?

To define an interface in TypeScript, use the “interface” keyword followed by the name of the interface and a set of curly braces that contain the members of the interface. For example:

interface Point {
  x: number;
  y: number;
  distanceToOrigin(): number;
}

How do you implement an interface in a class or object in TypeScript?

To implement an interface in a class or object in TypeScript, use the “implements” keyword followed by the name of the interface. Then, define the properties and methods specified in the interface and provide an implementation for them. For example:

class CartesianPoint implements Point {
  x: number;
  y: number;

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

  distanceToOrigin() {
    return Math.sqrt(this.x * this.x + this.y * this.y);
  }
}

Can an interface have optional members in TypeScript?

Yes, an interface can have optional members in TypeScript by marking them with a “?” symbol. This means that an object that implements the interface does not have to include these optional members. For example:

interface Point {
  x: number;
  y: number;
  label?: string;
}