TypeScript Classes

A class is a blueprint for creating objects. It bundles data (properties) and the actions that work on that data (methods) into a single reusable unit. TypeScript enhances JavaScript classes with access modifiers, typed properties, abstract classes, and constructor parameter shortcuts, making them far more powerful for building real-world applications.

Class Blueprint Concept

  Class (Blueprint)           Objects (Created from blueprint)
  +-----------------+         +------------------+
  | Student         |         | student1         |
  |-----------------|  -----> | name: "Ritu"     |
  | name: string    |         | age: 20          |
  | age: number     |  -----> +------------------+
  | study(): void   |         | student2         |
  +-----------------+         | name: "Mohan"    |
                              | age: 22          |
                              +------------------+

Defining a Class

class Student {
    name: string;
    age: number;
    grade: string;

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

    introduce(): string {
        return "I am " + this.name + ", age " + this.age + ", Grade: " + this.grade;
    }
}

let s1 = new Student("Ritu", 20, "A");
let s2 = new Student("Mohan", 22, "B+");

console.log(s1.introduce()); // I am Ritu, age 20, Grade: A
console.log(s2.introduce()); // I am Mohan, age 22, Grade: B+

Access Modifiers

Access modifiers control which parts of a program can see and use a class property or method. TypeScript supports three modifiers:

ModifierAccessible FromUse Case
publicAnywhere (default)Normal properties and methods
privateOnly inside the same classInternal data not for outside use
protectedInside the class and subclassesData shared with child classes
class BankAccount {
    public holderName: string;
    private balance: number;
    protected accountType: string;

    constructor(name: string, initialBalance: number) {
        this.holderName = name;
        this.balance = initialBalance;
        this.accountType = "Savings";
    }

    deposit(amount: number): void {
        this.balance += amount;  // private — accessible inside
        console.log("Deposited: ₹" + amount);
    }

    getBalance(): number {
        return this.balance;     // private — only returned via this method
    }
}

let acc = new BankAccount("Kaveri", 10000);
acc.deposit(5000);
console.log(acc.getBalance());    // 15000
console.log(acc.holderName);      // Kaveri
console.log(acc.balance);         // Error: 'balance' is private

Constructor Shorthand

TypeScript provides a shorthand for declaring and initializing class properties directly in the constructor parameters. Adding an access modifier before a parameter automatically creates and assigns the property.

// Long form
class Product {
    name: string;
    price: number;
    constructor(name: string, price: number) {
        this.name = name;
        this.price = price;
    }
}

// Shorthand — same result, less code
class Product {
    constructor(
        public name: string,
        public price: number,
        private stock: number
    ) {}
}

let p = new Product("Pen", 20, 500);
console.log(p.name);  // Pen
console.log(p.price); // 20

Readonly Properties in Classes

class Vehicle {
    constructor(
        public readonly vehicleId: string,
        public brand: string,
        public model: string
    ) {}
}

let car = new Vehicle("V-1001", "Maruti", "Swift");
car.brand = "Hyundai";      // Allowed
car.vehicleId = "V-2000";   // Error: Cannot assign to 'vehicleId' (read-only)

Inheritance

A class can inherit from another class using the extends keyword. The child class gets all the properties and methods of the parent class and can add its own.

  Inheritance Structure:
  +------------------+
  |   Person         |  (Parent / Base class)
  |  name, age       |
  |  greet()         |
  +--------+---------+
           |
    +------+------+
    |             |
+--------+    +----------+
|Employee|    | Student  |  (Child / Derived classes)
|empId   |    | rollNo   |
|dept    |    | grade    |
+--------+    +----------+
class Person {
    constructor(
        public name: string,
        public age: number
    ) {}

    greet(): string {
        return "Hi, I am " + this.name;
    }
}

class Employee extends Person {
    constructor(
        name: string,
        age: number,
        public empId: number,
        public department: string
    ) {
        super(name, age);  // Call parent constructor
    }

    introduce(): string {
        return this.greet() + " | Emp ID: " + this.empId + " | Dept: " + this.department;
    }
}

let emp = new Employee("Anil", 30, 1001, "Finance");
console.log(emp.introduce());
// Output: Hi, I am Anil | Emp ID: 1001 | Dept: Finance

Method Overriding

A child class can override a parent method to provide its own implementation. The override keyword makes this explicit and prevents accidental overrides.

class Animal {
    speak(): string {
        return "Some generic sound";
    }
}

class Dog extends Animal {
    override speak(): string {
        return "Woof!";
    }
}

class Cat extends Animal {
    override speak(): string {
        return "Meow!";
    }
}

let dog = new Dog();
let cat = new Cat();
console.log(dog.speak()); // Woof!
console.log(cat.speak()); // Meow!

Static Properties and Methods

Static members belong to the class itself, not to individual objects. They are shared across all instances and accessed using the class name.

class Counter {
    static count: number = 0;

    constructor() {
        Counter.count++;  // Increment class-level counter
    }

    static getCount(): number {
        return Counter.count;
    }
}

let c1 = new Counter();
let c2 = new Counter();
let c3 = new Counter();

console.log(Counter.getCount()); // 3

Abstract Classes

An abstract class provides a partial implementation that child classes must complete. An abstract class cannot be instantiated directly — it serves only as a base template. Methods marked abstract have no body; each child class must implement them.

abstract class Shape {
    abstract getArea(): number;   // No implementation here

    describe(): void {
        console.log("This shape has area: " + this.getArea());
    }
}

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

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

class Rectangle extends Shape {
    constructor(private width: number, private height: number) { super(); }

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

let circle = new Circle(7);
let rect   = new Rectangle(5, 10);

circle.describe();  // This shape has area: 153.93...
rect.describe();    // This shape has area: 50

let s = new Shape(); // Error: Cannot create an instance of an abstract class.

Implementing Interfaces in Classes

interface Printable {
    print(): void;
}

interface Saveable {
    save(): void;
}

class Report implements Printable, Saveable {
    constructor(private content: string) {}

    print(): void {
        console.log("Printing: " + this.content);
    }

    save(): void {
        console.log("Saving: " + this.content);
    }
}

let report = new Report("Monthly Sales Data");
report.print(); // Printing: Monthly Sales Data
report.save();  // Saving: Monthly Sales Data

Leave a Comment