Skip to content

Classes with Types

TypeScript adds structure, safety, and clarity to JavaScript’s class syntax. You get:

  • typed fields
  • typed constructors
  • visibility modifiers
  • abstract classes
  • parameter properties
  • strict initialization checks

Let’s break these down.


Access Modifiers

TypeScript adds three visibility modifiers to class members:

  • public — accessible everywhere (default)
  • private — accessible only inside the class
  • protected — accessible inside the class and subclasses

These modifiers exist only at compile time—they do not change JavaScript’s runtime behavior.


Public (default)

class User {
  public name: string

  constructor(name: string) {
    this.name = name
  }
}

const u = new User("Alice")
console.log(u.name) // ✔ OK

You can omit public because it’s the default.


Private

class BankAccount {
  private balance: number = 0

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

const acc = new BankAccount()
acc.deposit(100)
acc.balance // ❌ Error: private

Private members enforce encapsulation and prevent accidental misuse.


Protected

class Animal {
  protected move() {
    console.log("Moving...")
  }
}

class Dog extends Animal {
  bark() {
    this.move() // ✔ OK (protected)
  }
}

const d = new Dog()
d.move() // ❌ Error: protected

Protected is perfect for template methods and inheritance patterns.


Parameter Properties

Parameter properties are a TypeScript feature that reduces boilerplate in constructors.

Instead of writing:

class User {
  name: string
  age: number

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

You can write:

class User {
  constructor(
    public name: string,
    public age: number
  ) {}
}

This:

  • declares the fields
  • assigns them
  • applies access modifiers

All in one place.

Supported modifiers

  • public
  • private
  • protected
  • readonly

Example with readonly

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

const p = new Point(10, 20)
p.x = 5 // ❌ Error: readonly

Parameter properties are extremely common in idiomatic TypeScript.


Abstract Classes

Abstract classes define a base class that cannot be instantiated directly.

They are used to enforce structure in subclasses.

Basic abstract class

abstract class Shape {
  abstract area(): number

  describe() {
    return `Area: ${this.area()}`
  }
}

Subclass must implement abstract methods

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

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

const c = new Circle(10)
console.log(c.describe()) // Works

Trying to instantiate the abstract class:

new Shape() // ❌ Error

Why abstract classes matter

  • enforce consistent APIs across subclasses
  • provide shared logic + required overrides
  • ideal for frameworks, engines, and domain models

Classes + Interfaces

Classes can implement interfaces to enforce structure.

interface Serializable {
  serialize(): string
}

class User implements Serializable {
  constructor(public name: string) {}

  serialize() {
    return JSON.stringify({ name: this.name })
  }
}

This ensures the class provides the required methods.


Putting It All Together

Here’s a realistic example combining access modifiers, parameter properties, and abstract classes:

abstract class Repository<T> {
  protected items: T[] = []

  add(item: T) {
    this.items.push(item)
  }

  abstract findById(id: string): T | undefined
}

interface Entity {
  id: string
  name: string
}

class UserRepository extends Repository<Entity> {
  findById(id: string) {
    return this.items.find(item => item.id === id)
  }
}

const repo = new UserRepository()
repo.add({ id: "1", name: "Alice" })
console.log(repo.findById("1"))

This example demonstrates:

  • abstract base class
  • protected fields
  • generics
  • interface implementation
  • concrete subclass behavior

This is the foundation of OOP in TypeScript.


Summary

In this lesson, you learned how TypeScript enhances classes with:

1. Access modifiers

  • public, private, protected
  • compile‑time visibility enforcement

2. Parameter properties

  • concise constructor syntax
  • automatic field declaration + assignment
  • supports readonly

3. Abstract classes

  • enforce required methods
  • provide shared logic
  • cannot be instantiated directly

These features make TypeScript’s class system far more expressive and safer than plain JavaScript, while staying fully compatible with JavaScript’s runtime model.