any, unknown, dan never
Tiga tipe spesial: any yang berbahaya, unknown yang aman, never yang mustahil.
Analogi: Tiga Jalur di Bandara
Bayangkan bandara dengan tiga jalur pemeriksaan. Jalur pertama bertuliskan "lewat bebas, tidak diperiksa": cepat, tapi penyelundup juga lewat. Itu any. Jalur kedua memeriksa semua barang sebelum boleh lewat: agak lama, tapi aman. Itu unknown. Jalur ketiga adalah pintu yang tidak pernah dibuka untuk siapa pun: tidak ada yang bisa lewat, karena memang tidak ada yang boleh ada di sana. Itu never.
Ketiganya menangani "ketidakpastian", tapi dengan filosofi berlawanan. Memahami bedanya adalah pembeda antara kode TypeScript yang aman dan kode TypeScript yang cuma JavaScript berkedok.
Kenapa Tiga Tipe Ini Ada?
Dunia nyata itu berantakan. Data dari API, input user, hasil JSON.parse : semuanya datang tanpa jaminan bentuk. TypeScript butuh cara untuk berkata "aku belum tahu ini apa" tanpa berbohong bahwa ia tahu. any adalah jawaban lama yang terlalu permisif (mematikan pemeriksaan), unknown adalah jawaban modern yang jujur (memaksa pemeriksaan dulu), dan never adalah jawaban untuk "ini tidak mungkin terjadi" yang berguna untuk menangkap logika yang bolong.
Contoh 1: any Itu Menular
any berarti "jangan periksa apa pun tentang nilai ini". Sekali dipakai, ia menular ke semua yang menyentuhnya:
let data: any = "halo";
data = 42; // boleh, tidak dicek
const hasil = data * 2; // hasil: any (menular!)
hasil.tidakAda(); // lolos compiler, meledak saat runtimeSatu any bisa meracuni seluruh rantai: variabel yang diturunkan darinya ikut menjadi any, dan compiler buta total di sepanjang rantai itu. Pakai any hanya sebagai jalan terakhir, misalnya saat migrasi kode JavaScript lama yang belum sempat diberi tipe.
Contoh 2: unknown Memaksa Jujur, never Menangkap yang Mustahil
unknown berarti "tidak tahu, jadi periksa dulu sebelum dipakai":
function prosesRespons(respons: string): number {
const data: unknown = JSON.parse(respons);
if (typeof data === "object" && data !== null && "total" in data) {
const total = (data as { total: unknown }).total;
if (typeof total === "number") {
return total;
}
}
throw new Error("respons tidak valid");
}Setiap langkah dipersempit dulu lewat pengecekan. Repot? Sedikit. Tapi tidak ada lagi kejutan runtime dari data API yang bentuknya berubah diam-diam.
never untuk hal yang tidak mungkin terjadi, dan justru karena itu ia jadi alat pendeteksi logika bolong:
type Status = "sukses" | "gagal" | "pending";
function pesanStatus(s: Status): string {
switch (s) {
case "sukses": return "Berhasil!";
case "gagal": return "Gagal, coba lagi.";
case "pending": return "Mohon tunggu...";
default:
const sisa: never = s; // memastikan tidak ada kasus yang terlewat
throw new Error(`Status tak dikenal: ${sisa}`);
}
}Trik const sisa: never = s disebut exhaustiveness check: kalau besok Status tambah varian baru misalnya "batal", compiler langsung protes di baris ini karena s tidak lagi never. Kamu dipaksa menangani varian baru itu.
Contoh Nyata: Error Compiler Beraksi
Dua error klasik dari dua tipe ini:
// Kasus 1: memakai unknown tanpa pemeriksaan
let data: unknown = "halo";
data.toUpperCase();Error: 'data' is of type 'unknown'.
// Kasus 2: memaksa nilai masuk ke never
function mustahil(): never {
throw new Error("selalu gagal");
}
const x: never = "ada";Error: Type 'string' is not assignable to type 'never'.
Error pertama adalah unknown yang menjalankan tugasnya: melindungimu dari asumsi. Error kedua menunjukkan sifat never: tidak ada nilai apa pun yang boleh menempatinya, karena ia melambangkan ketiadaan.
Kesalahan Umum Pemula
1. Memakai any sebagai default saat malas mikir tipe
// SALAH: checklist dimatikan, bug kembali seperti di JavaScript
function jumlahkan(a: any, b: any): any {
return a + b;
}
jumlahkan("1", 2); // "12", tidak ada yang protes
// BENAR: tergoda pakai any? Pakai unknown + narrow
function jumlahkan(a: unknown, b: unknown): number {
if (typeof a !== "number" || typeof b !== "number") {
throw new Error("keduanya harus number");
}
return a + b;
}2. Mem-bypass unknown dengan as tanpa pengecekan
// SALAH: assertion buta, sama berbahayanya dengan any
function ambilNama(data: unknown): string {
return (data as { nama: string }).nama; // kalau data bukan object? Meledak.
}
// BENAR: persempit dulu dengan pengecekan nyata
function ambilNama(data: unknown): string {
if (typeof data === "object" && data !== null && "nama" in data) {
const nama = (data as { nama: unknown }).nama;
if (typeof nama === "string") return nama;
}
throw new Error("data tidak punya nama string");
}3. Mengira never sama dengan void
// SALAH: fungsi yang return undefined dikira never
function logPesan(pesan: string): never {
console.log(pesan); // Error: Type 'void' is not assignable to type 'never'.
}
// BENAR: void = tidak mengembalikan nilai (tapi selesai normal).
// never = tidak pernah selesai normal (throw atau infinite loop).
function logPesan(pesan: string): void {
console.log(pesan);
}
function gagalTotal(pesan: string): never {
throw new Error(pesan); // tidak pernah kembali
}Catatan teknis: Di strict mode, parameter fungsi tanpa anotasi menjadi implicit
anydan error (noImplicitAny). Ini fitur, bukan bug: compiler memaksamu sadar setiap kali type safety dimatikan, jadi tidak adaanyyang menyelinap diam-diam.
Tantangan
Amankan any
Fungsi berikut memakai any dan berbahaya. Refactor agar memakai unknown + pengecekan typeof, sehingga hanya string yang diproses dan tipe lain ditolak dengan pesan error yang jelas.
function cetakPanjang(data: any): number {
return data.length;
}
console.log(cetakPanjang("halo")); // 4Kuis Bab
Uji pemahamanmu: Fondasi TypeScript
Jawab 5 soal berikut, lalu tekan "Periksa Jawaban".
1.Apa keuntungan utama TypeScript dibanding JavaScript?
2.Apa fungsi file tsconfig.json?
3.Apa beda null dan undefined di TypeScript strict mode?
4.Kapan sebaiknya memakai unknown dibanding any?
5.Apa itu type inference?