Type assertion adalah cara bilang ke TypeScript: "percaya aku, nilai ini bertipe X". Ditulis dengan kata as. TypeScript berhenti mengecek dan langsung percaya, tapi nilainya sendiri gak berubah sedikit pun. Mirip menempel label "gula" di toples: semua orang percaya labelnya, tapi kalau isinya garam, kopimu tetap asin.
🧪 Tebakan cepat:
const user = JSON.parse('{"umur":17,"aktif":true}') as User, laluuser.nama.toUpperCase(). TypeScript protes gak? Dan apa yang terjadi waktu kodenya jalan? Tebak dulu, jawabannya ada di bagian "Assertion gak mengubah datanya".
as: kamu yang menjamin tipenya
Kadang kamu tahu lebih banyak dari TypeScript. Contohnya elemen HTML. TypeScript gak membaca file HTML-mu, jadi document.getElementById("email") cuma dikenal sebagai HTMLElement | null: elemen apa saja, atau gak ada. Tipe HTMLElement gak punya value, jadi baris kedua di bawah ditolak:
// Di HTML-mu ada <input id="email">
const el = document.getElementById("email")
el.value = "[email protected]"
// error TS18047: 'el' is possibly 'null'.
// error TS2339: Property 'value' does not exist on type 'HTMLElement'.
const input = document.getElementById("email") as HTMLInputElement
input.value = "[email protected]" // OK
as HTMLInputElementartinya "anggap ini input".HTMLInputElementpunyavalue, jadi error-nya hilang.- Sekalian,
nullikut dibuang dari tipenya. Kamu yang menjamin elemennya ada.
Contoh kedua: JSON.parse selalu mengembalikan any, karena TypeScript gak tahu isi teks JSON sebelum kodenya jalan. Orang sering menulis JSON.parse(teks) as User supaya hasilnya punya tipe.
Assertion gak mengubah datanya
Type cuma ada waktu TypeScript mengecek. Sebelum kode jalan, semua type dihapus, termasuk as User. Ini kodenya, dan JS yang tersisa:
type User = { nama: string }
const teks = '{"umur":17,"aktif":true}'
const data: unknown = JSON.parse(teks)
const user = data as User // TypeScript: gak ada error
console.log(user.nama.toUpperCase())
// JS setelah type dihapus
const teks = '{"umur":17,"aktif":true}'
const data = JSON.parse(teks)
const user = data
console.log(user.nama.toUpperCase())
unknown artinya "belum tahu isinya", jadi TypeScript menolak data.nama sebelum ada yang menjamin. as User adalah jaminan itu. Hasilnya untuk tiga isi teks:
Isi teks |
TypeScript | Console waktu jalan |
|---|---|---|
{"nama":"Budi"} |
gak ada error | BUDI |
{"umur":17,"aktif":true} |
gak ada error | TypeError: Cannot read properties of undefined (reading 'toUpperCase') |
null |
gak ada error | TypeError: Cannot read properties of null (reading 'nama') |
Itu jawaban tebakannya: TypeScript diam saja, lalu programnya crash waktu jalan. Teks kedua gak punya nama, jadi user.nama itu undefined. Pesan error di tabel adalah pesan Chrome dan Node; browser lain menulisnya sedikit beda.
Yang ditolak as, dan yang lolos
as cuma menolak yang jelas mustahil, yaitu dua tipe yang sama sekali gak nyambung:
const n = "17" as number
// 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.
const m = "17" as unknown as number // gak ada error
m.toFixed(1) // waktu jalan: TypeError: m.toFixed is not a function
as unknown as number(double assertion) melewati semua pengecekan. Isinya tetap teks"17", jadi crash.- Tanda
!di belakang nilai (non-null assertion) adalah janji "ini bukannullatauundefined".document.getElementById("judull")!lolos dari TypeScript, tapi kalau id-nya salah ketik,judul.textContent = "Halo"crash denganTypeError: Cannot set properties of null (setting 'textContent').
satisfies: dicek, tapi tipenya tetap
satisfies (sejak TypeScript 4.9) kebalikan dari as: dia mengecek nilainya cocok dengan sebuah type, tapi gak mengganti tipe yang ditebak TypeScript.
type Config = { port: number | string }
const a: Config = { port: 3000 }
a.port.toFixed(0)
// error TS2339: Property 'toFixed' does not exist on type 'string | number'.
const b = { port: 3000 } satisfies Config
b.port.toFixed(0) // OK: b.port tetap number
const c = { port: true } satisfies Config
// error TS2322: Type 'boolean' is not assignable to type 'string | number'.
Karena satisfies benar-benar mengecek, dia gak bisa dipakai buat data yang belum jelas. data satisfies User dengan data: unknown ditolak: error TS1360: Type 'unknown' does not satisfy the expected type 'User'.
Data dari luar: cek dengan type guard
Data dari server, localStorage atau input user gak bisa dijamin dengan as. Yang aman adalah type guard dari pelajaran type narrowing: fungsi yang benar-benar mengecek isinya waktu jalan.
function isUser(x: unknown): x is User {
return typeof x === "object" && x !== null && "nama" in x && typeof x.nama === "string"
}
const data: unknown = JSON.parse(teks)
if (isUser(data)) {
console.log(data.nama.toUpperCase()) // di sini data: User
} else {
console.log("Bukan User")
}
Dengan {"nama":"Budi"} hasilnya BUDI. Dengan {"umur":17,"aktif":true} atau null hasilnya Bukan User, gak ada crash. Pengecekan typeof dan in tetap ada di JS, gak ikut dihapus.
⚠️ Jebakan yang sering ketemu
- Mengira
asmengubah data.ascuma mengubah apa yang dipercaya TypeScript. Teks gak jadi angka, dan objek gak tiba-tiba punyanama. - Mengembalikan teksnya, bukan objeknya. Di latihan,
parseJSON('{"nama":"Budi"}')harus mengembalikan objek{"nama":"Budi"}.return jsonmengembalikan teks aslinya. KembalikanJSON.parse(json). - Membiarkan
: anysebagai tipe kembalian.anymenerima apa saja, jadias numberyang keliru pun lolos tanpa error. Dengan tipe kembalianRecord<string, unknown>, TypeScript langsung menolaknya:error TS2322: Type 'number' is not assignable to type 'Record<string, unknown>'.Latihannya menjalankan pemeriksa TypeScript, jadi error ini bikin gagal. as unknown asdan!buat membungkam error. Error-nya hilang dari editor, tapi pindah jadi crash waktu jalan.
TL;DR: as Tipe menyuruh TypeScript percaya, tanpa mengecek dan tanpa mengubah nilainya, karena semua type dihapus sebelum kode jalan. as cuma menolak tipe yang mustahil (TS2352); as unknown as dan ! gak menolak apa pun, jadi kesalahannya muncul sebagai crash. satisfies mengecek nilai yang kamu tulis sendiri dan tetap menyimpan tipe aslinya. Untuk data dari luar, pakai type guard yang mengecek isinya waktu jalan. JSON.parse mengembalikan any: objek hasil uraian teksnya.