Classes in TypeScript

Learning About Classes in TypeScript

Classes in TypeScript

Welcome back to our TypeScript series! Today, we’ll explore classes, a key feature that brings object-oriented programming to TypeScript. We'll cover class properties and methods, constructors, inheritance, access modifiers, abstract classes, and more.

1. Basic Class Syntax

A class is a blueprint for creating objects with properties and methods.

class Person {
  name: string;
  age: number;

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

  greet() {
    console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
  }
}

let alice = new Person("Alice", 25);
alice.greet(); // "Hello, my name is Alice and I am 25 years old."

In TypeScript, a class can have a special method called a constructor. The constructor is automatically called when a new instance(object) of the class is created. It is used to initialize the object's properties.

2. Class Properties and Methods

Properties are variables that belong to the class, and methods are functions that belong to the class.

class Rectangle {
  width: number;
  height: number;

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

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

let rect = new Rectangle(5, 10);
console.log(rect.area()); // 50

3. Access Modifiers

TypeScript supports access modifiers to control the visibility of class members. The three main modifiers are public, private, and protected.

  • Public: Members are accessible from anywhere. This is the default.

  • Private: Members are only accessible within the class.

  • Protected: Members are accessible within the class and its subclasses.

class Person {
  public name: string;
  private age: number;
  protected address: string;

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

  public getAge(): number {
    return this.age;
  }
}

let bob = new Person("Bob", 30, "123 Main St");
// console.log(bob.age); // Error: 'age' is private
console.log(bob.getAge()); // 30

4. Inheritance

Inheritance allows a class to extend another class, inheriting its properties and methods.

class Animal {
  name: string;

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

  move(distance: number) {
    console.log(`${this.name} moved ${distance} meters.`);
  }
}

class Dog extends Animal {
  bark() {
    console.log("Woof! Woof!");
  }
}

let dog = new Dog("Rex");
dog.bark(); // "Woof! Woof!"
dog.move(10); // "Rex moved 10 meters."

5. Getters and Setters

Getters and setters allow you to define methods that get and set the values of properties.

class Person {
  private _age: number;

  constructor(age: number) {
    this._age = age;
  }

  get age(): number {
    return this._age;
  }

  set age(newAge: number) {
    if (newAge > 0 && newAge < 150) {
      this._age = newAge;
    } else {
      console.log("Please enter a valid age.");
    }
  }
}

let john = new Person(25);
console.log(john.age); // 25
john.age = 30;
console.log(john.age); // 30
john.age = -5; // "Please enter a valid age."

6. Static Properties and Methods

Static properties and methods belong to the class itself, rather than instances of the class.

class MathUtils {
  static PI: number = 3.14;

  static calculateCircumference(diameter: number): number {
    return this.PI * diameter;
  }
}

console.log(MathUtils.PI); // 3.14
console.log(MathUtils.calculateCircumference(10)); // 31.4

7. Abstract Classes

Abstract classes are base classes that cannot be instantiated. They can contain abstract methods, which must be implemented by derived classes (subclasses).

abstract class Animal {
  abstract makeSound(): void;

  move(): void {
    console.log("Moving...");
  }
}

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

let dog = new Dog();
dog.makeSound(); // "Woof! Woof!"
dog.move(); // "Moving..."

8. Interfaces vs. Classes

While interfaces define the shape of an object, classes provide implementation. Classes can implement interfaces to ensure they adhere to a specific structure.

interface Drawable {
  draw(): void;
}

class Circle implements Drawable {
  draw() {
    console.log("Drawing a circle.");
  }
}

let circle = new Circle();
circle.draw(); // "Drawing a circle."

9. Example Code

Here's an example that combines various class features:

class Employee {
  private _fullName: string;

  constructor(public firstName: string, public lastName: string) {
    this._fullName = `${firstName} ${lastName}`;
  }

  get fullName(): string {
    return this._fullName;
  }

  static company: string = "Tech Corp";

  static getCompany(): string {
    return this.company;
  }

  greet() {
    console.log(`Hello, my name is ${this.fullName} and I work at ${Employee.company}.`);
  }
}

let emp = new Employee("Alice", "Johnson");
emp.greet(); // "Hello, my name is Alice Johnson and I work at Tech Corp."
console.log(Employee.getCompany()); // "Tech Corp"

Summary

Today, we delved into classes in TypeScript, covering class properties and methods, constructors, inheritance, access modifiers, getters and setters, static properties and methods, and abstract classes. Understanding these concepts will help you write more organized and maintainable object-oriented code in TypeScript.

Next time, we’ll explore generics in TypeScript. Stay tuned!