172 – Interfaces and classes in TypeScript (Javascript)

TypeScript – Interfaces and Classes in TypeScript

In TypeScript, interfaces and classes are essential concepts for defining and organizing code. They allow you to create blueprints for objects and provide a way to structure your applications. In this guide, we’ll explore how to use interfaces and classes effectively in TypeScript.

1. Interfaces in TypeScript

An interface defines a contract that an object must adhere to. It specifies the structure and behavior an object should have. Here’s an example:


interface Shape {
  area(): number;
}

class Circle implements Shape {
  constructor(private radius: number) {}

  area(): number {
    return Math.PI * this.radius * this.radius;
  }
}

const myCircle = new Circle(5);
console.log(myCircle.area()); // Output: 78.54

In this example, the `Shape` interface defines a contract for objects that should have an `area` method. The `Circle` class implements this interface, ensuring it has the required method. Interfaces help establish a clear structure for your code.

2. Class-Based Objects

Classes in TypeScript allow you to create objects with predefined structures and behaviors. They are similar to classes in other object-oriented programming languages. Here’s an example of a class:


class Person {
  constructor(public name: string, public age: number) {}

  sayHello(): string {
    return `Hello, my name is ${this.name} and I'm ${this.age} years old.`;
  }
}

const person = new Person("Alice", 30);
console.log(person.sayHello()); // Output: Hello, my name is Alice and I'm 30 years old.

Classes help encapsulate data and behavior in a single unit, promoting code organization and reusability.

3. Extending Classes

Classes can also inherit properties and methods from other classes. This inheritance concept promotes code reusability. Here’s an example of class inheritance:


class Employee extends Person {
  constructor(name: string, age: number, public role: string) {
    super(name, age);
  }

  introduce(): string {
    return `I'm an employee with the role of ${this.role}.`;
  }
}

const employee = new Employee("Bob", 25, "Developer");
console.log(employee.sayHello()); // Output: Hello, my name is Bob and I'm 25 years old.
console.log(employee.introduce()); // Output: I'm an employee with the role of Developer.

The `Employee` class extends the `Person` class, inheriting its properties and methods. This inheritance pattern simplifies the code and encourages consistency.

4. Implementing Multiple Interfaces

In TypeScript, a class can implement multiple interfaces. This feature is valuable when you need to ensure that an object adheres to several contracts. Here’s an example:


interface Driveable {
  start(): void;
  stop(): void;
}

interface Playable {
  play(): void;
}

class Car implements Driveable, Playable {
  start(): void {
    console.log("Car started.");
  }

  stop(): void {
    console.log("Car stopped.");
  }

  play(): void {
    console.log("Playing music in the car.");
  }
}

const myCar = new Car();
myCar.start(); // Output: Car started.
myCar.stop(); // Output: Car stopped.
myCar.play(); // Output: Playing music in the car.

In this example, the `Car` class implements both the `Driveable` and `Playable` interfaces, ensuring that it has the necessary methods from both interfaces.

5. Abstract Classes

Abstract classes provide a foundation for other classes to build upon. They cannot be instantiated themselves, but they can define methods that must be implemented by derived classes. Here’s an example:


abstract class Animal {
  abstract makeSound(): void;
}

class Dog extends Animal {
  makeSound(): void {
    console.log("Woof woof!");
  }
}

const myDog = new Dog();
myDog.makeSound(); // Output: Woof woof!

Abstract classes ensure that derived classes provide specific behavior, maintaining consistency in your application.

Conclusion

Interfaces and classes are fundamental building blocks in TypeScript. They help you define contracts, create structured objects, and organize your code. Understanding how to use them effectively is key to writing maintainable and well-structured TypeScript applications.