Pernyataan switch di TypeScript adalah switch milik JavaScript dengan pengecekan tipe. Ia membandingkan sebuah nilai dengan setiap case memakai ===, menjalankan cabang yang cocok, dan berhenti di break atau return. TypeScript mempersempit nilai yang di-switch di dalam setiap case dan bisa mengecek bahwa setiap nilai yang mungkin sudah ditangani.
Label yang ditumpuk (case "sat": case "sun":) berbagi satu cabang. return mengakhiri fungsi, jadi tidak perlu break setelahnya.
Sintaks
switch (expression) {
case value1:
// runs when expression === value1
break;
case value2:
case value3:
// runs for value2 or value3
break;
default:
// runs when nothing else matched
}
- Pencocokan memakai kesamaan ketat,
===:case 1tidak cocok dengan string"1". - Tanpa
break,returnatauthrow, eksekusi berlanjut ke case berikutnya (fallthrough). defaultbersifat opsional dan boleh ditaruh di mana saja, walaupun lazimnya di akhir.- Nilai
caseyang bisa dibuktikan TypeScript tidak pernah cocok adalah error TS2678. Untuk parameter bertipe"a" | "b",case "c":melaporkanType '"c"' is not comparable to type '"a" | "b"'., sehingga salah ketik di label case ketahuan.
Narrowing di Dalam Setiap Case
Di setiap case, TypeScript tahu nilai mana yang cocok dan mempersempit tipenya. Ini paling berguna dengan discriminated union: lakukan switch pada property tag yang sama-sama dimiliki, dan setiap case melihat varian yang cocok beserta property miliknya sendiri.
shape.radius hanya lolos kompilasi di case "circle". Di luar case itu, shape bisa saja persegi panjang, yang tidak punya radius. Tidak ada default, dan fungsinya tetap lolos pengecekan tipe sebagai fungsi yang mengembalikan number, karena TypeScript melihat bahwa ketiga case sudah mencakup setiap kind. Pola lain yang dibangun di atas ini ada di halaman discriminated unions.
Exhaustive Switch dengan never
Fungsi di atas berhenti lolos kompilasi kalau bentuk keempat ditambahkan tanpa case (TS2366, return yang hilang). Itu hanya berhasil kalau fungsinya mengembalikan nilai. Untuk jaminan yang juga berlaku di kode void dan memberi pesan yang lebih jelas, tambahkan default yang meng-assign nilainya ke never:
index.ts(14,19): error TS2322: Type '{ kind: "triangle"; base: number; height: number; }' is not assignable to type 'never'.
Setelah case-case yang ditangani, satu-satunya tipe yang tersisa untuk shape adalah varian segitiga, dan varian itu tidak bisa di-assign ke never. Error-nya menyebut persis apa yang terlewat. Tambahkan case "triangle": return (shape.base * shape.height) / 2; dan default melihat never, sehingga bloknya lolos kompilasi dan mencetak 9. throw tetap menjaga dari data yang buruk saat runtime, seperti kind dari JSON yang tidak diantisipasi oleh tipenya.
Banyak codebase membungkus pengecekan ini dalam sebuah helper:
Teknik yang sama berlaku untuk enum: lakukan switch pada nilai enum dan kirim nilainya ke assertNever di default.
switch (true) untuk Rentang dan Kondisi
switch membandingkan nilai, jadi rentang butuh trik: lakukan switch pada true dan tulis kondisi di setiap case. Sejak TypeScript 5.3, kondisi-kondisi itu mempersempit tipe seperti pernyataan if.
Case diuji secara berurutan, jadi taruh yang paling spesifik lebih dulu. Apakah cara ini lebih enak dibaca daripada if / else if adalah soal selera; perilakunya sama.
Fallthrough dan break
Case yang punya kode tetapi tanpa break, return atau throw akan berlanjut ke case berikutnya. Itu hampir selalu bug. Opsi compiler noFallthroughCasesInSwitch (bukan bagian dari strict) mengubahnya menjadi error TS7029, Fallthrough case in switch., sambil tetap mengizinkan label kosong yang ditumpuk.
Fallthrough yang disengaja seperti ini memang berfungsi, tetapi kalau noFallthroughCasesInSwitch aktif, kodenya harus ditulis ulang, misalnya dengan pengecekan if yang terpisah. Biasanya cara itu memang lebih jelas.
Variabel di Dalam Case
Seluruh isi switch adalah satu blok, jadi const yang dideklarasikan di satu case terlihat di case lain (dan mendeklarasikannya ulang adalah error). Bungkus sebuah case dengan kurung kurawal supaya ia punya scope sendiri:
Tanpa kurung kurawal, const unit yang kedua adalah error kompilasi TS2451, Cannot redeclare block-scoped variable 'unit'.
switch vs Lookup Object
Kalau setiap case hanya memetakan satu nilai ke nilai lain, object bertipe Record lebih ringkas, dan TypeScript mengecek bahwa setiap key ada:
Melewatkan sebuah key adalah error kompilasi, yang memberi kelengkapan yang sama seperti pengecekan never. Pakai switch untuk case yang menjalankan logika berbeda, mempersempit varian union, atau melakukan return lebih awal.
Pertanyaan yang sering diajukan
Bagaimana cara menulis pernyataan switch di TypeScript?
Persis seperti di JavaScript: switch (value) { case "a": ...; break; default: ... }. Case dibandingkan dengan ===. TypeScript menambahkan pengecekan: nilai case yang tidak mungkin cocok dengan tipe yang di-switch adalah error (TS2678), dan di dalam setiap case variabel yang di-switch dipersempit sesuai case itu.
Bagaimana cara membuat switch yang exhaustive di TypeScript?
Tambahkan default yang meng-assign nilainya ke variabel bertipe never: default: { const unreachable: never = value; throw new Error(...) }. Kalau setiap anggota union sudah ditangani, nilainya bertipe never di sana dan kodenya lolos kompilasi. Kalau ada yang terlewat, compiler melaporkan anggota yang terlewat itu (TS2322).
Bagaimana cara menangani beberapa case dengan kode yang sama di switch TypeScript?
Tumpuk label-labelnya tanpa kode di antaranya: case "sat": case "sun": return "weekend";. Case yang kosong akan berlanjut ke case berikutnya. Opsi noFallthroughCasesInSwitch hanya melaporkan case yang punya kode tetapi tidak punya break atau return, jadi label yang ditumpuk tetap diizinkan.
Apakah switch (true) mempersempit tipe di TypeScript?
Ya, sejak TypeScript 5.3. Di switch (true) { case typeof x === "string": ... }, x dipersempit menjadi string di dalam case itu, sama seperti di if. Ini alternatif yang mudah dibaca untuk rangkaian if/else if dengan pengecekan rentang atau tipe.