Class Dasar di TypeScript
Class dengan anotasi properti, constructor shorthand, dan method bertipe.
Kenapa class masih dipakai di dunia TypeScript
Di frontend React modern, class memang jarang terlihat. Tapi di backend (NestJS), ORM (TypeORM), dan domain logic yang butuh enkapsulasi kuat, class adalah warga kelas satu: dependency injection butuh class sebagai token, entity database dimodelkan sebagai class, dan invariant bisnis ("saldo tidak boleh negatif") paling enak dikunci di dalam method. TypeScript membuat class JavaScript jauh lebih aman lewat anotasi properti, modifier akses, dan constructor shorthand.
Class domain yang realistis: Rekening
class Rekening {
readonly id: string; // tidak bisa diubah setelah dibuat
private saldo: number; // hanya bisa diakses dari dalam class
// Constructor shorthand: "public" otomatis membuat properti.
constructor(id: string, public pemilik: string, saldoAwal = 0) {
this.id = id;
this.saldo = saldoAwal;
}
setor(jumlah: number): void {
if (jumlah <= 0) throw new Error("jumlah harus positif");
this.saldo += jumlah;
}
tarik(jumlah: number): number {
if (jumlah > this.saldo) throw new Error("saldo tidak cukup");
this.saldo -= jumlah;
return jumlah;
}
cekSaldo(): number {
return this.saldo;
}
}
const rek = new Rekening("R-001", "Budi", 50000);
rek.setor(10000);
console.log(rek.cekSaldo()); // 60000
console.log(rek.pemilik); // "Budi", public boleh dibacaInvariant "saldo tidak boleh negatif" terkunci di dalam tarik(). Tidak ada kode luar yang bisa mengakali lewat assignment langsung, karena saldo itu private. Ini inti OOP yang sebenarnya: bukan sekadar grouping fungsi, tapi melindungi state.
Error compiler nyata, tiga yang paling sering
1. Properti tanpa inisialisasi (strict mode):
class Kucing {
nama: string; // ERROR
constructor() {}
}error TS2564: Property 'nama' has no initializer and is not definitely
assigned in the constructor.Strict mode memaksa setiap properti punya nilai awal atau diisi di constructor. Cara betulkan: beri nilai default (nama = ""), isi di constructor, atau tandai nama!: string (definite assignment assertion) kalau kamu yakin diisi lewat jalur lain seperti decorator ORM.
2. Menulis ke properti readonly:
rek.id = "R-999";error TS2542: Cannot assign to 'id' because it is a read-only property.readonly cocok untuk identifier dan config yang ditetapkan sekali saat konstruksi dan tidak boleh berubah selamanya.
3. Mengakses private dari luar:
console.log(rek.saldo);error TS2341: Property 'saldo' is private and only accessible
within class 'Rekening'.Inilah enkapsulasi yang ditegakkan compiler, bukan sekadar konvensi penamaan underscore yang bisa dilanggar siapa saja.
Kapan dipakai di project nyata
- NestJS dan backend ber-DI: service dan controller ditulis sebagai class, dependensi di-inject lewat constructor. Tanpa class, framework-nya tidak bisa memetakan dependensi.
- Entity ORM:
class User { @Column() nama: string }di TypeORM. Decorator butuh target berupa class untuk menempelkan metadata. - Domain logic ber-invariant: keranjang belanja, rekening bank, mesin status pesanan. Aturan bisnis dikunci di method, state dijaga
private, dunia luar hanya boleh berinteraksi lewat API publik class tersebut.
Catatan teknis:
privateTypeScript hanya dicek saat compile; saat runtime propertinya masih bisa diakses (berbeda dengan#saldomilik JavaScript yang benar-benar privat di runtime). Untuk rahasia yang tidak boleh bocor ke kode lain dalam satu proses (misalnya token di dalam library), pakai#privat JavaScript. Untuk enkapsulasi desain sehari-hari,privateTypeScript sudah lebih dari cukup.
Tantangan
Class AkunBank
Buat class AkunBank dengan constructor shorthand: public pemilik: string, private saldo: number = 0. Method: setor(j: number): void, tarik(j: number): boolean (gagal bila saldo kurang), cekSaldo(): number. Pastikan tarik tidak bisa membuat saldo negatif.
class AkunBank {
constructor(
public pemilik: string,
private saldo: number = 0
) {}
setor(j: number): void {
// ...
}
tarik(j: number): boolean {
// return false bila kurang
return true;
}
cekSaldo(): number {
return this.saldo;
}
}
const a = new AkunBank("Budi", 100000);
a.tarik(150000);
console.log(a.cekSaldo()); // tetap 100000