Enums — TypeScript

Enum mendefinisikan sekumpulan konstanta bernama: Numeric enum: enum Direction { Up, Down, Left, Right } // Up = 0, Down = 1, Left = 2, Right = 3 let dir…

Enum adalah sekumpulan konstanta bernama yang dibuat dengan kata kunci enum. Daripada menulis angka atau teks yang gampang salah ketik di mana-mana, tiap pilihan diberi nama: Status.Active, Status.Pending. Mirip tombol kipas angin: di tombolnya tertulis Mati, Pelan, Kencang, tapi di dalam mesinnya yang dipakai angka 0, 1, 2.

🧪 Tebakan cepat: di enum Status { Active, Inactive, Pending }, berapa nilai Status.Active? Dan setelah di-compile, object Status punya berapa kunci: 3 atau 6? Tebak dulu, jawabannya ada di bagian "Numeric enum dan reverse mapping".

Numeric enum dan reverse mapping

enum Status {
  Active,   // 0
  Inactive, // 1
  Pending,  // 2
}

console.log(Status.Active); // 0
console.log(Status[0]);     // Active

Kalau gak diberi nilai, anggota enum dinomori otomatis mulai dari 0. Jadi Status.Active bernilai 0, dan di enum Warna { Merah, Hijau, Biru } nilai Warna.Merah juga 0. Kalau anggota pertama diberi angka, sisanya melanjutkan: enum Level { Rendah = 1, Sedang, Tinggi } membuat Level.Tinggi bernilai 3.

Beda dengan type, enum gak hilang saat compile. Ini JavaScript yang ditulis tsc untuk Status:

var Status;
(function (Status) {
  Status[Status["Active"] = 0] = "Active";
  Status[Status["Inactive"] = 1] = "Inactive";
  Status[Status["Pending"] = 2] = "Pending";
})(Status || (Status = {}));

String enum

enum Status {
  Active = "active",
  Inactive = "inactive",
  Pending = "pending",
}

console.log(Status.Active); // active

Tapi enum itu ketat. Parameter bertipe Status gak menerima teks biasa, walau isinya sama persis:

getStatusLabel("active");
error TS2345: Argument of type '"active"' is not assignable to parameter of type 'Status'.

Kamu wajib menulis getStatusLabel(Status.Active).

Union literal dan object as const

Yang sering dipakai sebagai ganti enum adalah union literal (sudah kamu kenal):

type Status = "active" | "inactive" | "pending";

function getStatusLabel(status: Status): string {
  if (status === "active") return "Aktif";
  if (status === "inactive") return "Nonaktif";
  return "Menunggu";
}

getStatusLabel("active");  // "Aktif"
getStatusLabel("selesai"); // error
error TS2345: Argument of type '"selesai"' is not assignable to parameter of type 'Status'.

Teks yang benar langsung diterima, teks yang salah ditolak. Setelah compile, type Status hilang total: 0 baris JavaScript.

Butuh daftarnya juga saat program jalan, misalnya untuk mengisi dropdown? Pakai object biasa dengan as const:

const STATUS = {
  Active: "active",
  Inactive: "inactive",
  Pending: "pending",
} as const;

type Status = (typeof STATUS)[keyof typeof STATUS]; // "active" | "inactive" | "pending"

Kenapa banyak tim memilih union

Hampir semua fitur TypeScript cuma tipe yang dihapus saat compile. Enum termasuk sedikit fitur yang menghasilkan kode JavaScript sendiri. Akibatnya:

Enum tetap sah dan masih banyak dipakai di proyek lama. Untuk kode baru, union literal biasanya cukup, dan object as const kalau daftarnya juga dibutuhkan saat jalan.

⚠️ Jebakan yang sering ketemu

TL;DR: enum membuat konstanta bernama. Numeric enum dinomori dari 0 (Status.Active = 0, Warna.Merah = 0) dan menghasilkan object dengan reverse mapping (Status[0] = "Active", total 6 kunci). String enum memberi tiap anggota teks sendiri, jadi lebih mudah dibaca, tapi gak menerima teks biasa. Union literal seperti type Status = "active" | "inactive" | "pending" hilang total saat compile dan menerima teks yang benar, dan object as const dipakai kalau daftarnya juga butuh saat jalan. Banyak tim memilih union karena enum ditolak erasableSyntaxOnly dan gak bisa dijalankan Node secara langsung.

Yang akan kamu pelajari