🌱BeginnerObject Types & Interfaces

Classes in TypeScript

Access modifiers (public/private/protected), readonly, parameter properties, implements, and abstract classes.

Overview

TypeScript extends JavaScript classes with a full type system. The biggest additions are **access modifiers** and **property declarations**. - **`public`** (default) accessible from anywhere - **`private`** accessible only inside the class - **`protected`** accessible inside the class and its subclasses - **`readonly`** can only be set in the constructor **Parameter properties** are a TypeScript shorthand: `constructor(public name: string, private id: number)` simultaneously declares the properties and assigns them from constructor arguments no separate declarations needed. Classes can **implement** interfaces to ensure they satisfy a contract. **Abstract** classes cannot be instantiated directly and may have abstract methods that subclasses must implement.

Key Points

  • •`public` (default), `private`, `protected` control visibility of class members
  • •Parameter properties: `constructor(public name: string)` declares + assigns in one step
  • •`readonly` property: set once in constructor, immutable after
  • •`implements Interface` the class must provide all interface members; TypeScript checks it
  • •`abstract class` cannot be instantiated; may have `abstract` methods subclasses must implement
  • •TypeScript `private` is compile-time only; use `#field` for true runtime private fields
  • •`protected` allows subclass access useful for shared internal helpers

Examples

Access modifiers and parameter properties

class BankAccount {
  // Parameter properties: declare + assign in constructor
  constructor(
    public readonly owner: string,
    private balance: number = 0,
  ) {}

  deposit(amount: number): void {
    if (amount <= 0) throw new Error("Amount must be positive");
    this.balance += amount;
  }

  withdraw(amount: number): void {
    if (amount > this.balance) throw new Error("Insufficient funds");
    this.balance -= amount;
  }

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

  toString(): string {
    return `${this.owner}: $${this.balance.toFixed(2)}`;
  }
}

const acc = new BankAccount("Alice", 100);
acc.deposit(50);
acc.withdraw(30);
console.log(acc.toString());   // Alice: $120.00
// acc.balance = 999;          // Error: 'balance' is private

Implements interface and inheritance

interface Drawable {
  draw(): string;
}

interface Resizable {
  resize(factor: number): void;
}

abstract class Shape implements Drawable {
  abstract area(): number;
  abstract draw(): string;

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

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

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

  draw(): string {
    return `â—‹ Circle(r=${this.radius})`;
  }

  resize(factor: number): void {
    this.radius *= factor;
  }
}

const c = new Circle(5);
console.log(c.describe());   // Circle: area=78.54
console.log(c.draw());       // â—‹ Circle(r=5)
c.resize(2);
console.log(c.area().toFixed(2));  // 314.16

// new Shape();  // Error: cannot instantiate abstract class

Protected and class statics

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

  protected makeSound(): string {
    return "...";
  }

  speak(): string {
    return `${this.name} says ${this.makeSound()}`;
  }
}

class Dog extends Animal {
  protected makeSound(): string {
    return "Woof!";
  }
}

class Cat extends Animal {
  protected makeSound(): string {
    return "Meow!";
  }
}

const dog = new Dog("Rex");
const cat = new Cat("Whiskers");
console.log(dog.speak());   // Rex says Woof!
console.log(cat.speak());   // Whiskers says Meow!

// dog.makeSound();  // Error: protected not accessible outside class hierarchy

Common Mistakes

  • Using TypeScript `private` and expecting runtime protection it's compile-time only; use `#field` for true privacy
  • Forgetting to call `super()` in a derived class constructor TypeScript requires it before accessing `this`
  • Confusing `implements` with `extends` `implements` checks that a class satisfies an interface shape but doesn't inherit any implementation; `extends` inherits from a parent class

Note

Use parameter properties for simple data classes to eliminate boilerplate. Instead of declaring the property, adding a constructor body assignment, and writing the parameter, just write `constructor(public name: string)` and TypeScript handles the rest.

Exercises

Write TypeScript code to solve each exercise. Click Run to compile and execute it right here, then mark as done.

Loading editor…

Completed: 0 / 5 exercises

Knowledge Check

Question 1 of 4

What do TypeScript parameter properties do?