TypeScript adds type safety to JavaScript classes. You get familiar OOP syntax with compile-time checks on properties, methods, and inheritance.

Basic Class

  class Animal {
    name: string;

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

    speak(): void {
        console.log(`${this.name} makes a sound.`);
    }
}

const dog = new Animal('Rex');
dog.speak(); // "Rex makes a sound."
  

Parameter Properties

TypeScript can declare and assign constructor parameters in one step:

  class User {
    constructor(
        public id: number,
        public name: string,
        private password: string
    ) {}

    greet(): string {
        return `Hi, I'm ${this.name}`;
    }
}

const u = new User(1, 'Alice', 'secret');
console.log(u.greet()); // "Hi, I'm Alice"
// console.log(u.password); // Error: private
  

Access Modifiers

Modifier Visibility
public Default — accessible everywhere
protected Class and subclasses only
private Class only (enforced at compile time)
readonly Set once, then immutable
  class BankAccount {
    readonly accountNumber: string;
    private balance: number;

    constructor(accountNumber: string, initial: number) {
        this.accountNumber = accountNumber;
        this.balance = initial;
    }

    deposit(amount: number): void {
        if (amount > 0) this.balance += amount;
    }

    getBalance(): number {
        return this.balance;
    }
}
  

Inheritance

  class Vehicle {
    constructor(protected brand: string) {}

    describe(): string {
        return `${this.brand} vehicle`;
    }
}

class Car extends Vehicle {
    constructor(brand: string, public doors: number) {
        super(brand);
    }

    describe(): string {
        return `${this.brand} car with ${this.doors} doors`;
    }
}

const car = new Car('Toyota', 4);
console.log(car.describe()); // "Toyota car with 4 doors"
  

Use super() to call the parent constructor. Override methods with the same signature.

Abstract Classes

Abstract classes cannot be instantiated directly — subclasses must implement abstract members:

  abstract class Shape {
    abstract area(): number;

    describe(): string {
        return `Area: ${this.area().toFixed(2)}`;
    }
}

class Circle extends Shape {
    constructor(private radius: number) {
        super();
    }

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

const circle = new Circle(5);
console.log(circle.describe()); // "Area: 78.54"
  

Implementing Interfaces

  interface Printable {
    print(): void;
}

class Report implements Printable {
    constructor(public title: string, public body: string) {}

    print(): void {
        console.log(`=== ${this.title} ===\n${this.body}`);
    }
}
  

Classes pair well with interfaces for defining contracts. In the next chapter, generics let you write reusable, type-safe functions and data structures.