Access Modifiers & Parameter Properties

Control member visibility, and declare-plus-assign fields right in the constructor signature.

TypeScript offers three visibility keywords plus JavaScript's own private fields:

  • public — the default; visible everywhere.
  • protected — visible in the class and its subclasses.
  • private — visible only inside the declaring class (enforced at compile time).
  • #field — JavaScript's runtime hard-private, truly inaccessible from outside.

Parameter properties

Put a modifier in front of a constructor parameter and TypeScript declares the field and assigns it for you — no more this.x = x boilerplate.

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

That five-line class fully declares two readonly public fields. Modifiers and readonly combine freely, so private readonly is a common, expressive choice.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • A service class uses private constructor parameters to inject dependencies without exposing them to subclasses.
  • A domain entity uses public readonly constructor parameters to create an immutable value object concisely.
  • A base class marks a helper as protected so only its subclasses can call it, keeping it out of the public API.

More examples

Parameter properties shorthand

Constructor parameter properties declare, assign, and apply access modifiers in one step without property declarations.

Example · ts
class User {
  constructor(
    public readonly id: number,
    public name: string,
    private email: string,
  ) {}

  getEmail(): string { return this.email; }
}

const u = new User(1, 'Alice', '[email protected]');
console.log(u.id, u.name);
// u.email; // Error: private

Protected access in subclass

Protected members are accessible in subclasses but not from external code, a middle ground between private and public.

Example · ts
class Base {
  constructor(protected config: string) {}

  protected validate(): boolean {
    return this.config.length > 0;
  }
}

class Derived extends Base {
  run(): void {
    if (this.validate()) console.log('Config:', this.config);
  }
}

Private field vs # private

Contrasts TypeScript's private keyword (erased at runtime) with the # native private field (truly private in JS).

Example · ts
class Counter {
  private tsPrivate: number = 0;  // TypeScript-only
  #jsPrivate: number = 0;          // native JS private field

  increment(): void {
    this.tsPrivate++;
    this.#jsPrivate++;
  }

  get values(): [number, number] {
    return [this.tsPrivate, this.#jsPrivate];
  }
}

Discussion

  • Be the first to comment on this lesson.
Access Modifiers & Parameter Properties — TypeScript | SoundsCode