TypeScript Class Modifiers in Depth
Parameter properties declare class fields inside the constructor signature. This lesson also deepens protected access, readonly fields, and hash-private fields.
Parameter properties declare fields in the constructor
Each parameter carries a modifier, so each one is also a field. The describe method reads all three fields.
class Ticket {
constructor(
private readonly id: number,
public title: string,
protected priority: number
) {}
describe(): string {
return `#${this.id} ${this.title} (p${this.priority})`;
}
}
const ticket = new Ticket(7, "Fix login", 2);
console.log(ticket.describe());
console.log(ticket.title);A protected member works inside a subclass
The subclass reads and changes the protected balance through inherited code. No outside code touches the field directly.
class Account {
protected balance = 100;
protected fee(amount: number): void {
this.balance -= amount;
}
}
class Savings extends Account {
chargeFee(): void {
this.fee(5);
}
report(): number {
return this.balance;
}
}
const sav = new Savings();
sav.chargeFee();
console.log(sav.report());A protected member is refused from outside
The same field is reachable inside the class family only. Reading it through an instance from outside code fails.
class Account {
protected balance = 100;
showBalance(): number {
return this.balance;
}
}
const acc = new Account();
console.log(acc.balance);A hash-private field counts inside the class
The field name starts with #, so JavaScript itself hides it. Only methods of the class can reach it.
class Clicker {
#count = 0;
bump(): void {
this.#count++;
}
value(): number {
return this.#count;
}
}
const clicker = new Clicker();
clicker.bump();
clicker.bump();
clicker.bump();
console.log(clicker.value());Hash-private access and readonly writes are refused
Two refusals appear here. The first line reaches for the # field from outside, and the second assigns to a readonly field after construction.
class Vault {
#code = 4321;
readonly limit: number;
constructor(limit: number) {
this.limit = limit;
}
reveal(): number {
return this.#code;
}
}
const vault = new Vault(3);
console.log(vault.#code);
vault.limit = 9;Example
class Order {
#items = 0;
constructor(
public readonly code: string,
protected discount = 0
) {}
addItem(): void {
this.#items++;
}
summary(): string {
return `${this.code}: ${this.#items} items, discount ${this.discount}`;
}
}
class MemberOrder extends Order {
applyDiscount(): void {
this.discount = 10;
}
}
const order = new MemberOrder("ORD-1");
order.addItem();
order.addItem();
order.applyDiscount();
console.log(order.summary());
console.log(order.code);Key points
- A parameter property is a constructor parameter with an access modifier or readonly.
- The modifier turns the parameter into a field, with no separate declaration or assignment.
- A protected member is reachable inside the class and its subclasses.
- A protected member is refused from code outside the class family.
- A field written with a leading # is private by JavaScript itself, not only by the checker.
- A readonly field accepts its value during construction and refuses later assignment.
In this example, parameter properties declare the code and discount fields in one signature. The subclass sets the protected discount, and the hash-private item count stays inside the base class.
Try it Yourself
Edit the code, then press Run.
Running is simulated ยท TypeScript Playground
Exercise
Which constructor parameter declares a class field?