value as Type adalah type assertion: ia memberi tahu TypeScript untuk memperlakukan value sebagai Type. Orang menyebutnya cast, tetapi ini hanya instruksi untuk compiler. Assertion dihapus dari output JavaScript, tidak mengonversi apa pun, dan tidak mengecek apa pun saat runtime.
Inilah pemakaian yang umum: kamu tahu lebih banyak tentang sebuah nilai daripada yang bisa diketahui compiler (di sini, bentuk sebuah JSON), lalu kamu menyatakannya. Kalau kamu salah, tidak ada yang memperingatkanmu. Bagian berikutnya menunjukkan apa artinya itu dan kapan pengecekan saat runtime adalah pilihan yang lebih baik.
as dan Sintaks Kurung Sudut
Ada dua cara penulisan untuk assertion yang sama:
const someValue: unknown = "hello";
const a = someValue as string; // as syntax
const b = <string>someValue; // angle-bracket syntax, same meaning
Bentuk kurung sudut tidak diizinkan di file .tsx, karena <string> akan dibaca sebagai tag JSX. Pakai as di mana saja dan pertanyaan itu tidak akan pernah muncul. Assertion mengikat dengan longgar, jadi bungkus dengan tanda kurung kalau kamu melanjutkan ekspresinya: (value as string).length.
Assertion Tidak Mengonversi Nilai
Bagian inilah yang menyebabkan bug sungguhan. Assertion mengubah apa yang diyakini compiler tentang sebuah nilai, bukan nilainya sendiri:
Compiler meyakini bahwa asserted adalah number, jadi asserted + 1 lolos pengecekan tipe sebagai operasi aritmetika. Saat runtime, nilainya tetap string "42" dan JavaScript menyambungnya. Untuk mengubah tipe sebuah nilai, konversi nilainya: Number(x), String(x), Boolean(x), BigInt(x), new Date(x). Halaman string ke number membandingkan fungsi-fungsi konversi itu.
| Yang ingin kamu lakukan | Tulis | Efek saat runtime |
|---|---|---|
| Memberi tahu compiler tipe yang kamu ketahui | x as T | tidak ada |
| Mengubah string menjadi number | Number(x), parseInt(x, 10) | mengonversi |
| Mengubah apa pun menjadi string | String(x), `${x}` | mengonversi |
| Mengecek tipenya lebih dulu | type guard, typeof, instanceof | mengecek |
Apa yang Diizinkan Compiler
as tidak tanpa batas. TypeScript mengizinkan x as T kalau salah satu tipe assignable ke tipe lainnya: pelebaran ("a" as string, dog as Animal) dan penyempitan (animal as Dog, unknown as User) sama-sama boleh. Kalau tipenya sama sekali tidak beririsan, TypeScript menolaknya:
Compiler melaporkan index.ts(3,11): error TS2352: Conversion of type 'string' to type 'number' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. Pesannya sendiri menyebutkan jalan pintasnya: input as unknown as number. Double assertion itu lolos kompilasi, dan sama salahnya saat runtime seperti contoh di atas. Kalau kamu merasa membutuhkannya, perbaikan yang tepat biasanya adalah konversi (Number(input)) atau tipe yang berbeda.
Aturan irisan ini longgar untuk object. Object literal yang punya sebagian property-nya tetap diterima, dan begitulah as diam-diam meloloskan object yang belum lengkap:
Anotasi (const draft: User = { name: "Ada" }) atau satisfies User akan melaporkan email yang hilang (TS2741). Pakai as pada object literal hanya kalau kamu memang berniat melengkapinya nanti, dan utamakan membangun object yang lengkap.
as const Itu Berbeda
as const terlihat seperti assertion, tetapi melakukan kebalikan dari melonggarkan: ia membuat sebuah literal sesempit mungkin. String tetap menjadi literal type, array menjadi tuple readonly, dan property object menjadi readonly.
Ini aman, karena ia menggambarkan literal itu secara persis alih-alih mengklaim sesuatu yang tidak bisa dilihat compiler. (sizes as readonly string[] di dalam isSize adalah assertion pelebaran, yang juga aman: ia membuat includes menerima string apa pun.) Lihat literal types untuk penjelasan lebih lanjut.
Kapan Type Guard Adalah Alat yang Lebih Tepat
as adalah klaim; type guard adalah pengecekan. Di batas tempat data datang dari luar kodemu (JSON, fetch, localStorage, input pengguna, sebuah pesan), klaim itu bisa saja salah, dan assertion mengubah error yang jelas di batas itu menjadi error yang membingungkan di tempat lain.
Panduan kasar untuk alat-alat yang terlihat mirip:
| Alat | Dicek saat kompilasi | Dicek saat runtime | Pakai kalau |
|---|---|---|---|
Anotasi const x: T = ... | ya, sepenuhnya | tidak | kamu membangun nilainya sendiri |
satisfies T | ya, sepenuhnya, mempertahankan tipe hasil inferensi | tidak | object literal, konfigurasi |
as T | hanya "apakah tipenya beririsan" | tidak | kamu tahu lebih banyak daripada compiler |
x! | hanya menghapus null / undefined | tidak | kamu tahu nilainya sudah diisi |
Type guard x is T | isi guard-nya adalah kode biasa | ya | data dari luar |
Masih ada dua pemakaian as yang baik: mempersempit sesuatu yang tidak bisa diikuti compiler (entri Map yang kamu set dua baris sebelumnya, nilai dari library yang tidak bertipe), dan kode test yang membangun fixture parsial. Buat sekecil mungkin dan dekat dengan tempat kamu tahu klaim itu benar.
Pertanyaan yang sering diajukan
Apa fungsi as di TypeScript?
value as Type adalah type assertion: ia memberi tahu compiler untuk memperlakukan value sebagai Type sejak titik itu. Assertion dihapus dari JavaScript hasil kompilasi, jadi ia tidak melakukan konversi dan tidak melakukan pengecekan saat runtime. Kalau assertion-nya salah, program gagal belakangan, di tempat mana pun tipe yang salah itu dipakai.
Bagaimana cara melakukan casting tipe di TypeScript?
TypeScript tidak punya cast saat runtime. Pakai as (atau bentuk lama <Type>value) untuk mengubah tipe statis saat kamu tahu lebih banyak daripada compiler. Untuk benar-benar mengonversi nilai, panggil sebuah fungsi: Number("42"), String(42), Boolean(x), new Date(text).
Apa arti "as unknown as" di TypeScript?
Ini double assertion. TypeScript menolak x as T kalau kedua tipenya sama sekali tidak beririsan (error TS2352), dan melewati unknown lebih dulu akan mem-bypass pengecekan itu, karena apa pun bisa di-assert ke dan dari unknown. Cara ini mematikan pengecekan tipe untuk nilai itu sepenuhnya, jadi simpan hanya untuk test dan untuk kode yang tipenya sudah kamu verifikasi dengan cara lain.
Apa perbedaan as dan kurung sudut di TypeScript?
Artinya sama sekali tidak berbeda: <string>value dan value as string adalah assertion yang sama. Bentuk kurung sudut tidak bisa dipakai di file .tsx karena bentrok dengan JSX, jadi as adalah bentuk yang dipakai semua orang.
Apa perbedaan as dan satisfies?
as menimpa tipe hasil inferensi dan hanya mengecek sangat sedikit (property yang hilang diperbolehkan). satisfies mengecek nilai terhadap sebuah tipe, melaporkan property yang hilang atau berlebih, dan mempertahankan tipe hasil inferensi yang tepat. Utamakan satisfies untuk object literal, dan pakai as hanya kalau kamu benar-benar tahu lebih banyak daripada compiler.