TypeScript · Classes

Access Modifiers

Access modifiers decide who can touch a class member: everyone, only the class, or the class and its children. They are how you protect an object’s internal state.

Intermediate 5 min Lesson 16 of 29Examples target TypeScript 5.x with "strict": true.
Before you start:Classes
0/29 in TypeScript
On this page · 5 min · Intermediate

Learning objectives#

  • Use public, private and protected
  • Compare TypeScript private with JavaScript #private
  • Combine modifiers with readonly and static
  • Design classes with a small public surface

Explanation#

public (the default): accessible from anywhere.

private: accessible only inside the same class. protected: inside the class and its subclasses.

TypeScript’s private is a compile-time check only — at runtime the property is a normal one. JavaScript’s #field is enforced by the engine at runtime. Use #field when real privacy matters.

readonly can be combined with any modifier (private readonly). static members belong to the class itself: Config.defaultTimeout.

Syntax#

TypeScript Illustrative
class A {
  public x = 1;
  protected y = 2;
  private z = 3;
  #w = 4;           // runtime-private
  static count = 0;
}

Code example: Who can access what?#

TypeScriptWho can access what? Illustrative
class Employee {
  static company = 'Techie Babaji';
  public name: string;
  protected salary: number;
  private pan: string;
  #bankPin: number;


  constructor(name: string, salary: number, pan: string, pin: number) {
    this.name = name;
    this.salary = salary;
    this.pan = pan;
    this.#bankPin = pin;
  }
}


class Manager extends Employee {
  bonus() {
    return this.salary * 0.2;   // ✓ protected is visible in subclasses
    // return this.pan;         // ✗ Property 'pan' is private and only accessible within class 'Employee'
  }
}


const m = new Manager('Asha', 100000, 'ABCDE1234F', 4321);
m.name;                 // ✓ public
m.salary;               // ✗ Property 'salary' is protected and only accessible within class 'Employee' and its subclasses
Employee.company;       // ✓ static, accessed on the class


console.log((m as any).pan);   // 'ABCDE1234F' — TS private is only a compile-time check
// (m as any).#bankPin           // ✗ impossible even at runtime
Expected output
TypeScript rejects m.salary and this.pan. Casting to any bypasses TS private (it prints 'ABCDE1234F'), but #bankPin cannot be reached at all.

This example is illustrative. Copy or download it and run it in your own environment; the expected output is shown above.

Step-by-step explanation#

  1. static company belongs to the class, not each employee.
  2. Manager can read salary because it is protected.
  3. pan is private to Employee — even subclasses cannot see it.
  4. Outside code can only use public members.
  5. as any skips type checking and exposes the TS-private field at runtime.
  6. #bankPin stays private at runtime too.

Real-world use case#

A payment service keeps API keys and internal caches private, exposes a few public methods, and lets specialised subclasses use protected helpers.

Common mistakes#

Relying on private for security

TS private disappears after compilation. Never treat it as protection for secrets — they should not be in client code at all.

Making everything public

A large public surface means more code depends on internals, so changing them breaks others.

Overusing protected

Protected members become part of the contract with every subclass. Prefer private plus small protected hooks.

Best practices#

  • Default to private; make public only what callers need
  • Use #private when runtime privacy matters
  • Use protected sparingly
  • Use private readonly for injected dependencies

Remember this#

public = everyone. protected = family (class + children). private = only me.

private = compile-time lock. # = runtime lock.

static = belongs to the class, not the objects.

Practice exercise#

Your task: In class Car, make engineNumber private readonly, speed protected and model public. Add a static wheels = 4.

Need a hint?
Use parameter properties for the three instance fields.
Show solution
TypeScript Illustrative
class Car {
  static wheels = 4;
  constructor(
    public model: string,
    protected speed: number,
    private readonly engineNumber: string,
  ) {}
}

Mini quiz#

Access Modifiers quizMultiple choice Question 1 of 3

Which modifier allows access from subclasses but not from outside?

Score so far: 0/0

Want more? Practise all TypeScript MCQs · TypeScript interview questions

My notes#

Saved in this browser.

Progress is saved in this browser. Sign in to sync.