This episode covers class typing in TypeScript: property declarations, parameter properties, inheritance, access modifiers, readonly, and abstract classes with implements. You'll also see when OOP is the right choice.

A class in TypeScript is a JavaScript class strengthened by the type system. On top of standard class syntax, TypeScript adds property declarations that must be initialized, access modifiers enforced by the compiler, and the ability to mark members abstract. The result is OOP you can rely on for complex domain models.
Some of the modern community prefers functions and plain objects. Yet classes remain the primary choice in many codebases, especially those interacting with object-oriented frameworks or needing a clear behavioral interface.
Episode 9 dissects how to write typed classes, inherit from other classes, control member visibility, and design abstractions with abstract classes and interfaces.
Properties must be declared and initialized before use:
class Akun {
nama: string;
saldo: number;
constructor(nama: string, saldo: number) {
this.nama = nama;
this.saldo = saldo;
}
simpan(amount: number): void {
this.saldo += amount;
}
}The declarations nama: string and saldo: number are property contracts. The constructor accepts typed arguments and copies them into the properties. The simpan method modifies the balance with a number argument. TypeScript ensures no property is used before it's initialized.
TypeScript offers a concise way to declare properties directly from constructor parameters:
class Akun {
constructor(
public nama: string,
private saldo: number = 0,
) {}
tampilkanSaldo(): number {
return this.saldo;
}
}A parameter given a modifier like public or private automatically becomes a property. The code above is equivalent to declaring properties and copying them manually in the constructor, but far more concise.
A class can inherit properties and methods from another class:
class Tabungan extends Akun {
private bunga: number;
constructor(nama: string, saldo: number, bunga: number) {
super(nama, saldo);
this.bunga = bunga;
}
tambahBunga(): void {
const nilai = (this.saldo * this.bunga) / 100;
this.simpan(nilai);
}
}The extends keyword gives Tabungan everything Akun has. A subclass constructor must call super before touching this. Methods can be overridden to adjust behavior, and TypeScript checks type compatibility during overriding.
Modifiers control who may access a member:
class Rekening {
public pemilik: string;
protected history: string[] = [];
private pin: number;
constructor(pemilik: string, pin: number) {
this.pemilik = pemilik;
this.pin = pin;
}
}public is accessible from anywhere and is the default. protected is accessible only from inside the class and its subclasses. private is accessible only from inside the same class. These modifiers prevent use of internal members that should stay hidden, fully checked by the compiler.
Properties that must not change after initialization are marked readonly:
class Transaksi {
readonly id: string;
constructor(id: string) {
this.id = id;
}
}The id property can only be assigned at declaration or in the constructor. After that, rewriting it is an error. readonly can be combined with access modifiers like private readonly.
An abstract class is a blueprint that can't be instantiated directly:
abstract class Pembayaran {
abstract jumlah(): number;
deskripsi(): string {
return `Total: ${this.jumlah()}`;
}
}
class Kartu extends Pembayaran {
jumlah(): number {
return 50_000;
}
}The method abstract jumlah() is declared without a body; every subclass must implement it. Concrete methods like deskripsi can call abstract methods. This pattern forces consistent structure without copying implementations.
A class can also promise to satisfy an interface shape with implements:
interface Penyimpan {
simpan(data: string): void;
}
class FilePenyimpan implements Penyimpan {
simpan(data: string): void {
console.log(`Menulis: ${data}`);
}
}implements forces the class to provide every member the interface asks for. Unlike extends, there's no inheritance of implementation, only a structural check.
Warning
Classes give convenient structure, but they aren't always the answer. For plain data and transformations, ordinary objects with functions are simpler. Choose classes when you need state encapsulation, behavioral polymorphism, or to satisfy an interface from a library.
Episode 9 equips you with fully typed OOP: guaranteed properties, concise parameter properties, inheritance with type checking, access modifiers, and abstraction through abstract classes and interfaces.
Key takeaways:
extends inherits behavior; subclasses must call super.public is open, protected for subclasses, private for the class itself.readonly locks a property after initialization.implements enforces an interface contract.In the next episode 10 we'll discuss namespaces, modules, and type-only imports and exports — how to organize code and types into isolated units that are easy to import.