Skip to content

TypeScript Classes and Objects

Classes are the core concept of object-oriented programming (OOP), serving as blueprints for creating objects. TypeScript fully supports the class syntax introduced in ES6 and adds features like type annotations and access modifiers on top of it.

What are Classes and Objects?

  • Class: A template or blueprint used to describe the common properties (data) and behaviors (methods) of a category of objects.
  • Object: An instance of a class. Created using the new keyword, possessing the properties and methods defined by the class.

Defining a Class

Here's a simple class definition:

typescript
class Greeter {
    // Property
    greeting: string;

    // Constructor
    constructor(message: string) {
        this.greeting = message;
    }

    // Method
    greet() {
        return "Hello, " + this.greeting;
    }
}

// Create an instance of the class (an object)
let greeter = new Greeter("world");

console.log(greeter.greet()); // "Hello, world"

Inheritance

Inheritance is a mechanism that allows one class (subclass) to acquire the properties and methods of another class (parent class). Use the extends keyword to implement inheritance.

typescript
class Animal {
    name: string;
    constructor(theName: string) { this.name = theName; }
    move(distanceInMeters: number = 0) {
        console.log(`${this.name} moved ${distanceInMeters}m.`);
    }
}

// Snake is a subclass of Animal
class Snake extends Animal {
    constructor(name: string) {
        super(name); // Call the parent class constructor
    }
    move(distanceInMeters = 5) {
        console.log("Slithering...");
        super.move(distanceInMeters); // Call the parent class method
    }
}

let sam = new Snake("Sammy the Python");
sam.move();
// Slithering...
// Sammy the Python moved 5m.
  • super(): In a subclass constructor, you must call super() to execute the parent class constructor.
  • super.method(): Can be used to call overridden methods from the parent class.

Access Modifiers

TypeScript provides three access modifiers to control the accessibility of class members (properties and methods).

  • public (default): Members can be accessed anywhere. If you don't specify a modifier, it defaults to public.

  • private: Members can only be accessed within the class where they're declared. Neither subclasses nor class instances can access them.

    typescript
    class Person {
        private name: string;
        constructor(name: string) { this.name = name; }
        public greet() {
            console.log(`Hello, my name is ${this.name}`);
        }
    }
    
    let john = new Person("John");
    john.greet(); // OK
    // console.log(john.name); // Error: Property 'name' is private.
  • protected: Members can be accessed within the class where they're declared and in subclasses of that class, but not on class instances.

    typescript
    class Employee extends Person {
        private department: string;
        constructor(name: string, department: string) {
            super(name);
            this.department = department;
        }
        public getElevatorPitch() {
            // Can access protected members of parent class in subclass
            // return `Hello, my name is ${this.name} and I work in ${this.department}.`;
            // If name is protected, the above line is OK. If it's private, it will error.
        }
    }

Readonly Modifier (readonly)

The readonly keyword ensures that a property can only be initialized when declared or in the constructor, and cannot be modified afterward.

typescript
class Octopus {
    readonly name: string;
    readonly numberOfLegs: number = 8;
    constructor(theName: string) {
        this.name = theName;
    }
}

let dad = new Octopus("Man with the 8 strong legs");
// dad.name = "Man with the 3-piece suit"; // Error! name is readonly.

Static Properties and Methods (static)

Static members belong to the class itself, not to instances of the class. You can access them directly through the class name without creating an object.

typescript
class Grid {
    static origin = { x: 0, y: 0 };
    calculateDistanceFromOrigin(point: { x: number; y: number; }) {
        let xDist = (point.x - Grid.origin.x);
        let yDist = (point.y - Grid.origin.y);
        return Math.sqrt(xDist * xDist + yDist * yDist) / this.scale;
    }
    constructor(public scale: number) { }
}

console.log(Grid.origin); // { x: 0, y: 0 }
let grid1 = new Grid(1.0);

Abstract Classes (abstract)

Abstract classes serve as base classes for other classes. They cannot be directly instantiated. Abstract classes can contain abstract methods, which have no concrete implementation and must be implemented in derived classes.

typescript
abstract class Department {
    constructor(public name: string) {}

    printName(): void {
        console.log("Department name: " + this.name);
    }

    abstract printMeeting(): void; // Must be implemented in derived class
}

class AccountingDepartment extends Department {
    constructor() {
        super("Accounting and Auditing");
    }

    printMeeting(): void {
        console.log("The Accounting Department meets each Monday at 10am.");
    }
}

let department: Department; // Allowed to create a reference to an abstract type
// department = new Department(); // Error: Cannot create an instance of an abstract class
department = new AccountingDepartment(); // Allowed to instantiate and assign an abstract subclass
department.printName();
department.printMeeting();

Content is for learning and research only.