TypeScript Access Modifiers
Access modifiers are keywords that control who can read or change a property or method inside a class. TypeScript provides three access modifiers: public, private, and protected. Without them, every property is accessible from anywhere — which leads to bugs in large projects because any part of the code can accidentally change data it should not touch.
The Real-World Analogy
Picture a hospital:
+---------------------------------------------------+ | HOSPITAL | | | | Reception (public) → Anyone can walk in | | Doctor's Office → Only staff can enter | | (private) | | Staff Room → Staff + trainees allowed | | (protected) | +---------------------------------------------------+
Access modifiers work the same way for class members — they define which "rooms" are open and to whom.
The Three Access Modifiers
| Modifier | Accessible From | Typical Use |
|---|---|---|
public | Anywhere (inside class, outside class, subclasses) | Data meant to be used freely |
private | Only inside the class itself | Internal data no one else should touch |
protected | Inside the class + subclasses only | Data shared with child classes but not outsiders |
public Modifier
public is the default. Every property and method without a modifier is automatically public.
class Student {
public name: string;
public grade: string;
constructor(name: string, grade: string) {
this.name = name;
this.grade = grade;
}
public getReport(): string {
return `${this.name} — Grade: ${this.grade}`;
}
}
let s = new Student("Priya", "A");
console.log(s.name); // Priya — accessible outside
console.log(s.getReport()); // Priya — Grade: A
private Modifier
A private property exists only inside its own class. No outside code — not even a subclass — can read or change it directly.
class BankAccount {
public owner: string;
private balance: number; // only this class can touch balance
constructor(owner: string, initialBalance: number) {
this.owner = owner;
this.balance = initialBalance;
}
public deposit(amount: number): void {
if (amount > 0) {
this.balance += amount;
}
}
public withdraw(amount: number): void {
if (amount <= this.balance) {
this.balance -= amount;
} else {
console.log("Insufficient funds");
}
}
public getBalance(): number {
return this.balance; // controlled access through a method
}
}
let account = new BankAccount("Rakesh", 5000);
account.deposit(2000);
console.log(account.getBalance()); // 7000
// account.balance = 99999;
// Error: Property 'balance' is private
Why private Matters
Without private: account.balance = 99999; // anyone can cheat the system With private: Only deposit() and withdraw() can change the balance → The bank's rules are enforced automatically
protected Modifier
protected sits between public and private. Subclasses (child classes) can access protected members, but code outside the class hierarchy cannot.
class Employee {
public name: string;
protected baseSalary: number; // child classes can use this
constructor(name: string, salary: number) {
this.name = name;
this.baseSalary = salary;
}
public getDetails(): string {
return `${this.name} — Base Salary: ₹${this.baseSalary}`;
}
}
class Manager extends Employee {
private bonus: number;
constructor(name: string, salary: number, bonus: number) {
super(name, salary);
this.bonus = bonus;
}
public getTotalPay(): number {
return this.baseSalary + this.bonus; // baseSalary accessible here
}
}
let mgr = new Manager("Sunita", 80000, 20000);
console.log(mgr.getTotalPay()); // 100000
console.log(mgr.name); // Sunita (public — fine)
// console.log(mgr.baseSalary);
// Error: Property 'baseSalary' is protected
Access Modifier Diagram
CLASS HIERARCHY ACCESS RULES
─────────────────────────────────────────────────────
│ Same Class │ Subclass │ Outside Code
─────────────────────────────────────────────────────
public │ YES │ YES │ YES
protected │ YES │ YES │ NO
private │ YES │ NO │ NO
─────────────────────────────────────────────────────
Shorthand in Constructor
TypeScript allows declaring and initializing class properties directly in the constructor parameters. Adding a modifier before the parameter name creates the property automatically.
// Without shorthand — verbose
class Product {
public name: string;
private price: number;
constructor(name: string, price: number) {
this.name = name;
this.price = price;
}
}
// With shorthand — clean and short
class Product {
constructor(
public name: string,
private price: number
) {}
public getPrice(): number {
return this.price;
}
}
let p = new Product("Laptop", 65000);
console.log(p.name); // Laptop
console.log(p.getPrice()); // 65000
readonly Modifier
readonly prevents a property from being changed after it is set. It works alongside access modifiers.
class Certificate {
public readonly studentName: string;
public readonly issueDate: string;
constructor(name: string, date: string) {
this.studentName = name;
this.issueDate = date;
}
}
let cert = new Certificate("Ananya", "2026-01-15");
console.log(cert.studentName); // Ananya
console.log(cert.issueDate); // 2026-01-15
// cert.studentName = "Someone Else";
// Error: Cannot assign to 'studentName' because it is a read-only property
Practical Example: User Profile Class
class UserProfile {
public username: string;
private passwordHash: string;
protected email: string;
public readonly userId: number;
constructor(userId: number, username: string, email: string, password: string) {
this.userId = userId;
this.username = username;
this.email = email;
this.passwordHash = this.hashPassword(password);
}
private hashPassword(password: string): string {
// simplified — real code uses bcrypt or similar
return "hashed_" + password.length;
}
public checkPassword(password: string): boolean {
return this.passwordHash === this.hashPassword(password);
}
public getPublicInfo(): object {
return {
id: this.userId,
username: this.username
};
}
}
class AdminUser extends UserProfile {
public getEmail(): string {
return this.email; // protected — accessible in subclass
}
}
let user = new UserProfile(101, "rahuldev", "rahul@mail.com", "secret123");
console.log(user.username); // rahuldev
console.log(user.checkPassword("secret123")); // true
// user.passwordHash — Error: private
Summary
| Modifier | Default? | Inherited by Subclass? | Usable Outside? |
|---|---|---|---|
public | Yes | Yes | Yes |
private | No | No | No |
protected | No | Yes | No |
readonly | No | Yes | Yes (read only) |
