Access modifiers in TypeScript: public, private, protected, readonly
What are Access Modifiers?
Access modifiers control the visibility of class properties and methods. TypeScript adds public, private, protected, and readonly modifiers on top of JavaScript's class syntax.
public (Default)
Accessible from anywhere β this is the default:
typescript
class User {
public name: string; // Accessible everywhere
constructor(name: string) {
this.name = name;
}
public greet(): string {
return `Hello, ${this.name}`;
}
}
const user = new User("Alice");
user.name; // β
Accessible
user.greet(); // β
Accessibleprivate
Accessible only within the class itself:
typescript
class BankAccount {
private balance: number;
constructor(initial: number) {
this.balance = initial;
}
public deposit(amount: number): void {
this.balance += amount; // β
Access within class
}
public getBalance(): number {
return this.balance; // β
Access within class
}
}
const account = new BankAccount(1000);
account.deposit(500); // β
account.getBalance(); // β
account.balance; // β Error: Property 'balance' is privateTypeScript private vs JavaScript #private
typescript
class Example {
private tsPrv = 1; // TypeScript-only (compile-time)
#jsPrv = 2; // JavaScript runtime private (ES2022)
}
// TypeScript private: still accessible at runtime (no enforcement)
// JS # private: truly private at runtimeprotected
Accessible within the class and its subclasses:
typescript
class Animal {
protected name: string;
constructor(name: string) {
this.name = name;
}
protected makeSound(): string {
return "...";
}
}
class Dog extends Animal {
public bark(): string {
return `${this.name} says: Woof!`; // β
Access in subclass
}
public sound(): string {
return this.makeSound(); // β
Protected method accessible in subclass
}
}
const dog = new Dog("Rex");
dog.bark(); // β
"Rex says: Woof!"
dog.name; // β Error: Property 'name' is protectedreadonly
Can be set only in the constructor or at declaration β never modified after:
typescript
class Config {
readonly apiUrl: string;
readonly maxRetries: number = 3; // Default value
constructor(url: string) {
this.apiUrl = url; // β
Set in constructor
}
updateUrl() {
this.apiUrl = "new-url"; // β Error: Cannot assign to 'apiUrl'
}
}Parameter Properties (Shorthand)
typescript
// β Verbose
class User {
private name: string;
private age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
// β
Shorthand with parameter properties
class User {
constructor(
private name: string,
private age: number,
public readonly id: string
) {}
// Properties are automatically declared and assigned!
}Comparison Table
| Modifier | In class | In subclass | Outside |
|---|---|---|---|
public | β | β | β |
protected | β | β | β |
private | β | β | β |
readonly | Set once | Read only | Read only |
Important:
Use private for internal implementation details, protected for extension points in class hierarchies, and readonly for immutable properties. Prefer parameter properties (shorthand) to reduce boilerplate. For true runtime privacy, use JavaScript's # private fields.
Short Answer
Interview readyPremium
A concise answer to help you respond confidently on this topic during an interview.