TypeScript Classes

A practical guide to TypeScript classes, parameter properties, access modifiers, and inheritance mechanisms.

TL;DR

  1. Declare object blueprints using class and typed properties.
  2. Use public, private, and protected to control member visibility.
  3. Extend parent classes with extends and call super() constructors.

Class Syntax

    class declaration

    Declares an object blueprint with typed property signatures.

    class User {
      name: string;
      constructor(name: string) {
        this.name = name;
      }
    }
    new instance

    Instantiates an object and triggers its constructor execution.

    const user = new User('Morgan');
    console.log(user.name); // Morgan
    readonly modifier

    Prevents reassignment to a property outside initialization.

    class Config {
      readonly apiKey: string;
      constructor(key: string) {
        this.apiKey = key;
      }
    }
    instance method

    Defines functions shared across all class instances.

    class Account {
      balance: number = 0;
      deposit(amount: number): number {
        return this.balance += amount;
      }
    }

Parameter Properties

    public shorthand

    Declares and assigns public instance properties automatically.

    class Product {
      constructor(
        public title: string,
        public price: number
      ) {}
    }
    private shorthand

    Declares instance members accessible only within the class.

    class Vault {
      constructor(private secret: string) {}
      reveal(): string {
        return this.secret;
      }
    }
    readonly shorthand

    Combines parameter creation with immutability guarantees.

    class Coordinate {
      constructor(
        readonly x: number,
        readonly y: number
      ) {}
    }

Access Modifiers

    public keyword

    Allows unrestricted read and write access across all scopes.

    class Message {
      public content: string = '';
    }
    protected keyword

    Restricts access to the containing class and derived classes.

    class BaseService {
      protected log(msg: string) {
        console.log(`[SYS]: ${msg}`);
      }
    }
    # private field

    Provides true ECMAScript runtime encapsulation.

    class Counter {
      #value = 0;
      increment(): number {
        return ++this.#value;
      }
    }

Inheritance and Overrides

    extends keyword

    Derives a child class that inherits parent properties.

    class Animal {
      constructor(public species: string) {}
    }
    class Dog extends Animal {
      bark() { return 'woof'; }
    }
    super() call

    Executes parent constructor logic before subclass initialization.

    class Employee extends User {
      constructor(name: string, public dept: string) {
        super(name);
      }
    }
    override keyword

    Explicitly marks methods intended to replace parent methods.

    class Logger {
      write(msg: string) { console.log(msg); }
    }
    class JsonLogger extends Logger {
      override write(msg: string) {
        console.log(JSON.stringify({ msg }));
      }
    }

Static Members

    static method

    Attaches utility functions directly to the class constructor.

    class MathUtil {
      static double(n: number): number {
        return n * 2;
      }
    }
    MathUtil.double(21); // 42
    static property

    Shares a single variable across all callers and instances.

    class InstanceTracker {
      static activeSessions: number = 0;
      constructor() {
        InstanceTracker.activeSessions++;
      }
    }
    static block

    Executes complex initialization logic when class evaluates.

    class Registry {
      static cache: Map<string, string>;
      static {
        this.cache = new Map();
        this.cache.set('v1', 'active');
      }
    }

Tips

  1. Use parameter properties in constructor signatures to declare and assign class fields in a single line.
  2. Mark methods override in derived classes to ensure you match the parent class signature accurately.

Warnings

  1. Remember that the private keyword is compile-time only, so use # private fields for true runtime isolation.
  2. Calling instance methods before super() in a derived constructor triggers a fatal compile and runtime error.

In Practice

FAQ