readonly
Properti yang hanya bisa diisi sekali: readonly di class dan object.
Kenapa readonly Ada
Bug yang menyebalkan: id sebuah order berubah di tengah proses. Order ORD-1 tiba-tiba menjadi ORD-2 karena ada satu baris kode di sudut codebase yang assign ulang order.id. Tanpa readonly, compiler diam saja. Dengan readonly, baris itu langsung merah saat kamu menulisnya, bukan saat customer komplain.
readonly adalah cara termurah untuk menyatakan maksud: "properti ini diisi sekali saat object lahir, setelah itu jangan pernah diubah." Ini bukan soal keamanan dari hacker, tapi soal keamanan dari diri sendiri dan rekan tim enam bulan dari sekarang yang lupa aturan mainnya.
Kapan Dipakai di Project Nyata
- ID entity:
idorder, user, produk. ID tidak pernah berubah sepanjang hidup object. Di ORM seperti TypeORM atau Prisma, pola ini standar. - Config yang di-inject sekali:
apiUrl,timeout,apiKeydi service class. Diisi di constructor dari environment, lalu terkunci. - Timestamp:
dibuatPada: Dateyang diisinew Date()saat construction. - Parameter properties: shorthand
constructor(readonly id: string)sangat idiomatis untuk DTO dan entity, menghemat deklarasi properti manual.
Contoh 1: Entity Order yang ID-nya Tidak Bisa Diutak-atik
class Order {
readonly tanggal: Date = new Date();
constructor(
readonly id: string,
public status: string
) {}
}
const o = new Order("ORD-1", "baru");
o.status = "dikirim"; // OK, status memang boleh berubah
o.id = "ORD-2";
// Error: Cannot assign to 'id' because it is a read-only property. (TS2540)TS2540 muncul tepat di baris yang mencoba mengubah. Perhatikan readonly boleh diisi di dua tempat: saat deklarasi (tanggal) atau di constructor (id). Setelah construction selesai, keduanya terkunci permanen.
Contoh 2: Jebakan readonly yang Shallow
Ini jebakan paling umum. readonly hanya melarang reassign propertinya, bukan mutasi isi object-nya:
class Kos {
readonly penghuni: string[] = ["Budi"];
}
const kos = new Kos();
// kos.penghuni = []; // Error TS2540, reassign dilarang
kos.penghuni.push("Ani"); // LOLOS! isi array tetap bisa dimutasi
console.log(kos.penghuni); // ["Budi", "Ani"]Kalau kamu butuh array yang benar-benar tidak bisa diubah, gabungkan dua readonly:
class KosAman {
readonly penghuni: readonly string[] = ["Budi"];
}
const ka = new KosAman();
// ka.penghuni.push("Ani");
// Error: Property 'push' does not exist on type 'readonly string[]'. (TS2339)Aturan praktisnya: readonly di properti mengunci referensinya, readonly di tipe array mengunci isinya. Untuk object bertingkat, pertimbangkan utility type Readonly<T> atau library immutable bila datanya kompleks.
Contoh 3: readonly di Interface Response API
interface ResponApi {
readonly requestId: string;
readonly waktu: number;
data: unknown;
}
function proses(r: ResponApi): void {
// r.requestId = "x"; // Error TS2540
console.log(r.requestId, r.waktu);
}Pola ini bagus untuk response API: metadata seperti requestId tidak boleh diubah oleh kode hilir, tapi data tetap bisa diolah bebas.
Catatan teknis:
readonlyvsconst:constuntuk variabel (variabelnya tidak bisa di-reassign),readonlyuntuk properti (propertinya tidak bisa di-reassign setelah inisialisasi). Keduanya compile-time only dan hilang total di JavaScript hasil kompilasi, jadi tidak ada biaya runtime sama sekali.
Tantangan
Entity abadi
Buat class Order dengan readonly id: string, readonly tanggal: Date (isi dengan new Date()), dan public status: string. Buktikan id tidak bisa diubah setelah construction, tapi status bisa.
class Order {
readonly tanggal: Date = new Date();
constructor(
readonly id: string,
public status: string
) {}
}
const o = new Order("ORD-1", "baru");
o.status = "dikirim"; // OK
// o.id = "ORD-2"; // Error!Kuis Bab
Uji pemahamanmu: OOP & Modul
Jawab 5 soal berikut, lalu tekan "Periksa Jawaban".
1.Apa risiko memakai as (type assertion)?
2.Kapan memakai import type dibanding import biasa?
3.Apa fungsi implements pada class?
4.Apa beda private dan protected?
5.Apa arti readonly pada properti class?