Type guard adalah pemeriksaan saat runtime yang dipahami TypeScript, sehingga tipe di dalam cabang yang diperiksa ikut dipersempit. typeof, instanceof dan in adalah type guard bawaan; untuk hal lain, kamu menulis fungsi yang tipe kembaliannya berupa type predicate, value is Type.
Saat runtime, isUser hanya mengembalikan boolean biasa. Tipe kembalian value is User memberi tahu compiler apa yang dibuktikan oleh hasil true, lalu setiap if (isUser(x)) mempersempit x menjadi User.
Type Guard Bawaan
Pemeriksaan berikut mempersempit tipe tanpa fungsi bantu apa pun:
| Guard | Contoh | Dipakai untuk |
|---|---|---|
typeof | typeof x === "number" | tipe primitif dan fungsi |
instanceof | x instanceof Date | instance class |
in | "email" in x | union object, property dari object unknown |
Array.isArray | Array.isArray(x) | array |
| Kesamaan | x === null, x.kind === "circle" | null/undefined, penanda literal |
| Truthiness | if (x) | membuang null dan undefined |
Semuanya berjalan sebagai JavaScript biasa. Yang ditambahkan TypeScript adalah penyempitannya: ia membaca pemeriksaan itu dan menyesuaikan tipe di setiap cabang. Daftar lengkap bentuknya ada di halaman type narrowing. Type guard buatan sendiri dipakai untuk pemeriksaan yang tidak muat dalam satu ekspresi, atau yang ingin kamu pakai ulang.
Menulis Type Predicate
Type predicate berbentuk parameterName is Type dan menggantikan boolean sebagai tipe kembalian. Penyempitannya bekerja ke dua arah: true mempersempit ke Type, dan false membuang Type dari union.
Memberikan type guard ke filter menghasilkan array dengan tipe yang benar. Sejak TypeScript 5.5, compiler juga menyimpulkan predicate dari arrow function sederhana, jadi pets.filter((p) => p.kind === "cat") mengembalikan Cat[] tanpa type guard bernama.
Tipe predicate harus cocok dengan tipe parameternya: function f(x: string): x is number adalah error TS2677, A type predicate's type must be assignable to its parameter's type.
Compiler Memercayai Type Guard Kamu
TypeScript memeriksa bahwa type guard mengembalikan boolean. TypeScript tidak memeriksa apakah boolean itu benar. Type guard yang mengembalikan true untuk nilai yang salah membuat tipenya berbohong, dan program gagal saat runtime tanpa error kompilasi.
data.price.toFixed(2) melempar TypeError: Cannot read properties of undefined (reading 'toFixed') saat runtime. Compiler menerima data.price sebagai number karena type guard berkata begitu. Periksa setiap property yang diandalkan oleh sisa kode, dan buat type guard tetap kecil, teruji, dan dekat dengan tipe yang dijelaskannya.
Mengecek Apakah Object Punya Tipe Tertentu
Inilah pertanyaan di balik sebagian besar type guard buatan sendiri: data datang sebagai unknown (dari JSON.parse, fetch, localStorage, sebuah pesan) dan kamu perlu tahu apakah data itu cocok dengan interface-mu. Resepnya:
typeof value === "object" && value !== null(sebuah object, bukannull)."prop" in valueuntuk setiap property wajib. Padaunknown,inmenambahkan property itu ke tipenya sebagaiunknown.typeof value.prop === "..."(atau type guard bersarang) untuk tipe setiap property.Array.isArray(value.items) && value.items.every(isItem)untuk array.
Untuk bentuk yang besar atau bersarang dalam, menulis pemeriksaan seperti ini dengan tangan jadi melelahkan. Library schema seperti Zod atau Valibot memungkinkan kamu menjelaskan bentuknya sekali dan memberimu pemeriksaan runtime sekaligus tipe TypeScript-nya.
Assertion Function: asserts value is Type
Assertion function melempar error kalau pemeriksaannya gagal dan selesai seperti biasa kalau berhasil. Tipe kembaliannya adalah asserts value is Type (atau asserts condition), dan semua kode setelah pemanggilan sudah dipersempit, tanpa perlu if.
Ada satu aturan yang sering menjebak: assertion function harus dipanggil lewat nama yang punya tipe eksplisit. Arrow function const tanpa anotasi, const check = (v: unknown): asserts v is string => {...}, memberi error TS2775 di tempat pemanggilan, Assertions require every name in the call target to be declared with an explicit type annotation. Pakai deklarasi function, atau beri anotasi tipe fungsi pada konstanta itu.
Type Guard vs Assertion vs Cast
| Alat | Ada pemeriksaan runtime? | Mempersempit | Kalau gagal |
|---|---|---|---|
Type guard bawaan (typeof, in...) | Ya | di dalam cabang | masuk ke cabang lain |
Fungsi value is T | Ya (kodemu sendiri) | di dalam cabang | masuk ke cabang lain |
Fungsi asserts value is T | Ya (kodemu sendiri) | setelah pemanggilan | melempar error |
value as T | Tidak | ekspresi itu | tidak ada: tipe yang salah menyebar |
Type assertion (as) mengubah tipe tanpa memeriksa apa pun. Di batas tempat data datang dari luar, type guard atau assertion function adalah versi aman dari ide yang sama.
Type Guard Berbasis this di Class
Sebuah method bisa mempersempit object tempat ia dipanggil dengan this is Type. Ini berguna dalam hierarki class:
class FileNode {
constructor(public name: string) {}
isDirectory(): this is DirectoryNode {
return this instanceof DirectoryNode;
}
}
class DirectoryNode extends FileNode {
children: FileNode[] = [];
}
function count(node: FileNode): number {
return node.isDirectory() ? node.children.length : 0; // node: DirectoryNode in the true branch
}
Pertanyaan yang sering diajukan
Apa itu type guard di TypeScript?
Type guard adalah pemeriksaan saat runtime apa pun yang dipakai TypeScript untuk mempersempit tipe: typeof x === "string", x instanceof Date, "id" in x, Array.isArray(x), atau pemanggilan fungsi yang tipe kembaliannya berupa type predicate seperti x is User. Di dalam cabang yang sudah diperiksa, variabel itu punya tipe yang lebih sempit.
Bagaimana cara mengecek apakah sebuah object punya tipe tertentu di TypeScript?
Tipe tidak ada saat runtime, jadi yang kamu periksa adalah property-nya: tulis fungsi isUser(value: unknown): value is User yang mengecek typeof value === "object", value !== null, dan setiap property wajib dengan in dan typeof. Setelah if (isUser(x)), x bertipe User. Untuk class, x instanceof MyClass sudah cukup.
Apa arti "value is Type" di TypeScript?
Itu adalah type predicate, yang dipakai sebagai tipe kembalian fungsi. Saat runtime fungsi itu tetap mengembalikan boolean, tetapi ketika hasilnya true, TypeScript mempersempit argumennya menjadi Type di tempat pemanggilan, dan ketika hasilnya false, argumen itu dipersempit ke anggota union yang lain. Compiler tidak memverifikasi isi fungsi, jadi pemeriksaannya harus benar.
Apa perbedaan type guard dan assertion function?
Type guard (x is T) mengembalikan boolean dan mempersempit tipe di dalam if. Assertion function (asserts x is T) tidak mengembalikan apa pun dan melempar error kalau pemeriksaannya gagal, jadi semua kode setelah pemanggilan sudah dipersempit tanpa if. Pakai type guard untuk percabangan, dan assertion untuk "ini harus benar, kalau tidak, berhenti".
Bisakah mengecek apakah sebuah object mengimplementasikan interface di TypeScript?
Tidak secara langsung: interface dihapus saat kompilasi dan instanceof tidak menerimanya. Tulis type guard yang memeriksa property interface itu, atau tambahkan property penanda berupa literal (kind: "user") lalu bandingkan. Library schema seperti Zod membuat pemeriksaan dan tipenya sekaligus dari satu definisi.