TypeScript Classes
TypeScript classes are JavaScript classes with type annotations and extra features: access modifiers, readonly properties, parameter properties and abstract classes.
Typed Properties and Constructors
Properties must be declared with their types. With strict mode, each one must be initialized in the constructor or with a default.
class Product {
name: string;
price: number;
constructor(name: string, price: number) {
this.name = name;
this.price = price;
}
discounted(percent: number): number {
return this.price * (1 - percent / 100);
}
}
const p = new Product("Almonds", 15);
console.log(p.discounted(20));12
Access Modifiers
- public (default): accessible everywhere
- private: only inside the class (checked at compile time only)
- protected: inside the class and its subclasses
- #field: JavaScript private field, enforced at runtime too
Parameter Properties and readonly
Adding a modifier to a constructor parameter declares and assigns the property in one step, removing boilerplate.
class BankAccount {
constructor(
public readonly owner: string,
private balance: number = 0,
) {}
deposit(amount: number) {
this.balance += amount;
return this;
}
get summary() {
return `${this.owner}: ${this.balance}`;
}
}
const acc = new BankAccount("Usman").deposit(500).deposit(250);
console.log(acc.summary);
// acc.balance = 1e6; // Error: Property 'balance' is private.
// acc.owner = "Other"; // Error: Cannot assign to 'owner' because it is a read-only property.Usman: 750
Inheritance and protected
The override keyword marks a method that replaces a parent method; with noImplicitOverride the compiler requires it.
class Employee {
constructor(public name: string, protected salary: number) {}
describe() {
return `${this.name} earns ${this.salary}`;
}
}
class Manager extends Employee {
constructor(name: string, salary: number, private bonus: number) {
super(name, salary);
}
override describe() {
return `${super.describe()} + ${this.bonus} bonus`;
}
}
console.log(new Manager("Emma", 5000, 800).describe());Emma earns 5000 + 800 bonus
Abstract Classes
An abstract class cannot be instantiated. It provides shared code and declares abstract methods that subclasses must implement.
abstract class Notifier {
abstract send(msg: string): string;
notify(msg: string) {
return "[" + new Date(0).getUTCFullYear() + "] " + this.send(msg);
}
}
class EmailNotifier extends Notifier {
send(msg: string) {
return "Email: " + msg;
}
}
// new Notifier(); // Error: Cannot create an instance of an abstract class.
console.log(new EmailNotifier().notify("Order shipped"));[1970] Email: Order shipped
Frequently asked questions
What is the difference between private and # in TypeScript?
private is checked only by the compiler and disappears in JavaScript. #fields are real JavaScript private fields, enforced at runtime.
What are parameter properties in TypeScript?
Constructor parameters with a modifier like public, private or readonly. TypeScript turns them into class properties automatically.
When should I use an abstract class instead of an interface?
Use an abstract class when subclasses should share real code. Use an interface when you only need to describe a shape with no implementation.