Menu
Courses / TypeScript Basics / classes and oop

classes and oop

07 / 10 Part of TypeScript Basics

Classes in TypeScript


TypeScript builds on JavaScript's class syntax by adding type annotations, access modifiers, and stricter structure — making object-oriented code safer and easier to maintain.



Defining a Class


class Car {
    brand: string;
    color: string;
    speed: number;

    constructor(brand: string, color: string) {
        this.brand = brand;
        this.color = color;
        this.speed = 0;
    }

    accelerate(): void {
        this.speed += 10;
        console.log(`${this.brand} is now going ${this.speed} km/h`);
    }
}

const myCar = new Car("Toyota", "Red");
myCar.accelerate(); // Toyota is now going 10 km/h


Access Modifiers


TypeScript adds three access modifiers to control how properties and methods can be used from outside the class.



   
   
       
       
       
   
ModifierMeaning
publicAccessible from anywhere (the default if omitted)
privateAccessible only from within the same class
protectedAccessible within the class and its subclasses


class BankAccount {
    private balance: number;

    constructor(initialBalance: number) {
        this.balance = initialBalance;
    }

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

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

const account = new BankAccount(100);
account.deposit(50);
console.log(account.getBalance()); // 150
console.log(account.balance);      // Error: Property 'balance' is private


Shorthand Constructor Properties


TypeScript offers a shortcut: adding an access modifier directly to a constructor parameter automatically creates and assigns the matching property.


class BankAccount {
    constructor(private balance: number) {}

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

const acc = new BankAccount(200);
console.log(acc.getBalance()); // 200


Readonly Properties


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

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

const p = new Point(5, 10);
p.x = 20; // Error: Cannot assign to 'x' because it is a read-only property


Inheritance


class Animal {
    constructor(protected name: string) {}

    eat(): void {
        console.log(`${this.name} is eating.`);
    }
}

class Dog extends Animal {
    bark(): void {
        console.log(`${this.name} says Woof!`);
    }
}

const dog = new Dog("Rex");
dog.eat();  // Rex is eating.
dog.bark(); // Rex says Woof!


Overriding Methods


class Animal {
    makeSound(): void {
        console.log("Some generic animal sound");
    }
}

class Cat extends Animal {
    override makeSound(): void {
        console.log("Meow");
    }
}


    Note: The override keyword is optional but recommended — it makes your intent explicit and causes an error if the parent class doesn't actually have a matching method to override.


Abstract Classes


Like in many OOP languages, abstract classes cannot be instantiated directly and may define methods that subclasses are required to implement.


abstract class Shape {
    abstract area(): number;

    describe(): void {
        console.log(`This shape has an area of ${this.area()}`);
    }
}

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

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

const circle = new Circle(5);
circle.describe(); // This shape has an area of 78.53981633974483


Implementing Interfaces


A class can formally promise to match an interface's shape using implements.


interface Flyable {
    fly(): void;
}

class Bird implements Flyable {
    fly(): void {
        console.log("The bird flies through the sky.");
    }
}



    Coming up next: Generics — writing flexible, reusable code that still stays fully type-safe.