Menu

Type Guard TypeScript: Cara Mengecek Tipe Sebuah Object

Type guard adalah pemeriksaan saat runtime yang dipahami TypeScript. Pelajari type guard bawaan, cara menulis type guard sendiri dengan type predicate value is Type, cara mengecek apakah object punya tipe tertentu, assertion function dengan asserts, dan cara memvalidasi data unknown.

Halaman ini dilengkapi editor yang bisa dijalankan. Edit, jalankan, dan lihat output-nya seketika.

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:

GuardContohDipakai untuk
typeoftypeof x === "number"tipe primitif dan fungsi
instanceofx instanceof Dateinstance class
in"email" in xunion object, property dari object unknown
Array.isArrayArray.isArray(x)array
Kesamaanx === null, x.kind === "circle"null/undefined, penanda literal
Truthinessif (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.

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:

  1. typeof value === "object" && value !== null (sebuah object, bukan null).
  2. "prop" in value untuk setiap property wajib. Pada unknown, in menambahkan property itu ke tipenya sebagai unknown.
  3. typeof value.prop === "..." (atau type guard bersarang) untuk tipe setiap property.
  4. 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

AlatAda pemeriksaan runtime?MempersempitKalau gagal
Type guard bawaan (typeof, in...)Yadi dalam cabangmasuk ke cabang lain
Fungsi value is TYa (kodemu sendiri)di dalam cabangmasuk ke cabang lain
Fungsi asserts value is TYa (kodemu sendiri)setelah pemanggilanmelempar error
value as TTidakekspresi itutidak 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.

Ilustrasi bahasa pemrograman di Coddy

Belajar coding dengan Coddy

Mulai