Type Assertion dengan as
Memberi tahu compiler tipe yang kamu yakini: as, dan risikonya.
as: "percayalah, saya lebih tahu"
Type assertion adalah kamu berkata ke compiler: "sudahlah, saya yang tahu tipe aslinya". Sintaksnya nilai as Tipe.
let data: unknown = "halo";
let s = data as string; // "saya yakin ini string"
s.toUpperCase(); // compiler nurutPahami satu hal yang fundamental: as tidak mengubah nilai dan tidak melakukan konversi apa pun. Tidak ada runtime check, tidak ada transformasi data. Ia hanya mengganti kacamata compiler saat melihat nilai itu. Nilai di memorinya tetap sama persis seperti sebelum assertion.
Kapan as masuk akal: compiler buta, kamu tidak
Ada situasi di mana KAMU punya informasi yang mustahil diketahui compiler dari kode:
// Kamu yang menulis HTML-nya, kamu tahu #nama itu <input>.
const input = document.getElementById("nama") as HTMLInputElement;
input.value; // tanpa as, error: getElementById me-return HTMLElement | nullKasus sah lainnya: hasil JSON.parse yang strukturnya kamu kontrol penuh, atau interop dengan library JavaScript lama yang tipenya any. Polanya selalu sama: informasi tambahan datang dari luar kode yang bisa dilihat compiler, dan kamu adalah satu-satunya sumber informasi itu.
SALAH: as untuk data yang belum divalidasi
Ini pola paling berbahaya dan paling sering ditemui di codebase nyata:
interface User { id: number; nama: string }
const res = await fetch("/api/user/1");
const user = (await res.json()) as User; // SALAH tapi lolos compiler
console.log(user.nama.toUpperCase());Kalau API ternyata me-return { error: "not found" }, maka user.nama itu undefined, dan .toUpperCase() meledak saat runtime. Compiler diam saja, karena kamu yang menyuruh dia percaya. Bandingkan dengan yang benar:
const raw: unknown = await res.json();
if (adalahUser(raw)) { // type predicate, ada bukti runtime
console.log(raw.nama.toUpperCase()); // terverifikasi, aman
} else {
console.log("data user rusak, tampilkan pesan error");
}Bedanya satu kata kunci: verifikasi. as hanya mengklaim, guard membuktikan dengan pengecekan yang benar-benar dieksekusi.
Error compiler nyata: as pun ada batasnya
Compiler tidak membiarkan assertion yang jelas-jelas ngawur antar tipe yang tidak berhubungan:
const nama = "budi";
const angka = nama as number;error TS2352: Conversion of type 'string' to type 'number' may be a mistake
because neither type sufficiently overlaps with the other.Tapi ada celah yang sering disalahgunakan: lewat unknown dulu, semuanya bisa lolos.
const x = "halo" as unknown as number; // lolos compiler!
x.toFixed(2); // runtime: x.toFixed is not a function. Crash.Double assertion as unknown as T pada dasarnya menonaktifkan type checker untuk satu baris. Kalau kamu menemukannya saat code review, anggap itu bendera merah yang wajib ditanya alasannya.
Kapan dipakai di project nyata
- Kode DOM yang kamu tulis sendiri:
getElementById,querySelector,event.targetdi form yang strukturnya kamu kendalikan. Idealnya setelah null check. - Migrasi bertahap JS ke TS: file lama bertipe
anydi mana-mana,asdipakai sementara sambil tipe yang benar ditulis. Harus dicatat sebagai utang, bukan solusi permanen. - Test: bikin objek parsial lalu
aske tipe penuh biar tidak perlu mengisi 20 field yang tidak relevan dengan test itu. Di test, risikonya terkendali.
Catatan teknis: Aturan emasnya sederhana:
ashanya untuk kasus di mana kamu punya info yang tidak dimiliki compiler (struktur DOM yang kamu tulis, kontrak internal antar modul). Untuk data dari luar (API, JSON, form, query string, localStorage), JANGAN pakaias: validasi dengan type guard, assertion function, atau Zod. Makin sedikitasdi codebase, makin bisa dipercaya type safety-nya.
Tantangan
Assertion yang jujur
Diberikan const el = document.getElementById("email") (tipe HTMLElement | null). Tulis assertion yang benar ke HTMLInputElement SETELAH memastikan tidak null (pakai if atau pastikanAda). Jelaskan di komentar kenapa assertion di sini aman.
const el = document.getElementById("email");
// 1. pastikan tidak null dulu
// 2. assertion ke HTMLInputElement
// 3. akses .value