🌱BeginnerObject Types & Interfaces
Classes in TypeScript
Access modifiers (public/private/protected), readonly, parameter properties, implements, and abstract classes.
Overview
TypeScript extends JavaScript classes with a full type system. The biggest additions are **access modifiers** and **property declarations**.
- **`public`** (default) accessible from anywhere
- **`private`** accessible only inside the class
- **`protected`** accessible inside the class and its subclasses
- **`readonly`** can only be set in the constructor
**Parameter properties** are a TypeScript shorthand: `constructor(public name: string, private id: number)` simultaneously declares the properties and assigns them from constructor arguments no separate declarations needed.
Classes can **implement** interfaces to ensure they satisfy a contract. **Abstract** classes cannot be instantiated directly and may have abstract methods that subclasses must implement.
Key Points
- •`public` (default), `private`, `protected` control visibility of class members
- •Parameter properties: `constructor(public name: string)` declares + assigns in one step
- •`readonly` property: set once in constructor, immutable after
- •`implements Interface` the class must provide all interface members; TypeScript checks it
- •`abstract class` cannot be instantiated; may have `abstract` methods subclasses must implement
- •TypeScript `private` is compile-time only; use `#field` for true runtime private fields
- •`protected` allows subclass access useful for shared internal helpers
Examples
Access modifiers and parameter properties
class BankAccount {
// Parameter properties: declare + assign in constructor
constructor(
public readonly owner: string,
private balance: number = 0,
) {}
deposit(amount: number): void {
if (amount <= 0) throw new Error("Amount must be positive");
this.balance += amount;
}
withdraw(amount: number): void {
if (amount > this.balance) throw new Error("Insufficient funds");
this.balance -= amount;
}
getBalance(): number {
return this.balance;
}
toString(): string {
return `${this.owner}: $${this.balance.toFixed(2)}`;
}
}
const acc = new BankAccount("Alice", 100);
acc.deposit(50);
acc.withdraw(30);
console.log(acc.toString()); // Alice: $120.00
// acc.balance = 999; // Error: 'balance' is privateImplements interface and inheritance
interface Drawable {
draw(): string;
}
interface Resizable {
resize(factor: number): void;
}
abstract class Shape implements Drawable {
abstract area(): number;
abstract draw(): string;
describe(): string {
return `${this.constructor.name}: area=${this.area().toFixed(2)}`;
}
}
class Circle extends Shape implements Resizable {
constructor(private radius: number) {
super();
}
area(): number {
return Math.PI * this.radius ** 2;
}
draw(): string {
return `â—‹ Circle(r=${this.radius})`;
}
resize(factor: number): void {
this.radius *= factor;
}
}
const c = new Circle(5);
console.log(c.describe()); // Circle: area=78.54
console.log(c.draw()); // â—‹ Circle(r=5)
c.resize(2);
console.log(c.area().toFixed(2)); // 314.16
// new Shape(); // Error: cannot instantiate abstract classProtected and class statics
class Animal {
constructor(protected name: string) {}
protected makeSound(): string {
return "...";
}
speak(): string {
return `${this.name} says ${this.makeSound()}`;
}
}
class Dog extends Animal {
protected makeSound(): string {
return "Woof!";
}
}
class Cat extends Animal {
protected makeSound(): string {
return "Meow!";
}
}
const dog = new Dog("Rex");
const cat = new Cat("Whiskers");
console.log(dog.speak()); // Rex says Woof!
console.log(cat.speak()); // Whiskers says Meow!
// dog.makeSound(); // Error: protected not accessible outside class hierarchyCommon Mistakes
- Using TypeScript `private` and expecting runtime protection it's compile-time only; use `#field` for true privacy
- Forgetting to call `super()` in a derived class constructor TypeScript requires it before accessing `this`
- Confusing `implements` with `extends` `implements` checks that a class satisfies an interface shape but doesn't inherit any implementation; `extends` inherits from a parent class
Note
Use parameter properties for simple data classes to eliminate boilerplate. Instead of declaring the property, adding a constructor body assignment, and writing the parameter, just write `constructor(public name: string)` and TypeScript handles the rest.
Exercises
Write TypeScript code to solve each exercise. Click Run to compile and execute it right here, then mark as done.
Loading editor…
Completed: 0 / 5 exercises
Knowledge Check
Question 1 of 4