Kenapa ini penting
Tipe dasar adalah "kosakata" TypeScript. Sama seperti belajar bahasa asing dimulai dari kata benda dan kata kerja, semua tipe rumit nanti (generics, utility types, tipe props React) dibangun dari tipe-tipe dasar ini. Kalau kamu paham betul perbedaan any dan unknown, atau kapan TypeScript bisa menebak tipe sendiri, kamu akan menulis kode yang lebih ringkas sekaligus lebih aman.
Analoginya seperti wadah di dapur: toples gula, botol kecap, kotak telur. Setiap wadah dibuat untuk isi tertentu. Kalau kamu menuang kecap ke toples gula, kekacauan baru ketahuan saat seseorang membuat teh. Tipe adalah label di wadah itu, dan TypeScript adalah orang yang mencegahmu menuang isi yang salah.
Konsep inti
Tipe primitif
| Tipe | Contoh nilai | Catatan |
|---|---|---|
string |
"Sari", `Halo ${nama}` |
Semua teks |
number |
42, 3.14, NaN |
Bilangan bulat dan desimal sama-sama number |
boolean |
true, false |
|
bigint |
9007199254740993n |
Angka sangat besar |
symbol |
Symbol("id") |
Jarang dipakai di aplikasi biasa |
null |
null |
"Sengaja kosong" |
undefined |
undefined |
"Belum diisi" |
Perhatikan huruf kecil: string, bukan String. String (kapital) adalah object pembungkus di JavaScript dan hampir tidak pernah kamu perlukan sebagai tipe.
Inferensi tipe
Kamu tidak wajib menulis tipe di mana-mana. TypeScript menebak (infer) tipe dari nilai awal:
let kota = "Bandung"; // TypeScript menyimpulkan: string
kota = 123; // ❌ error TS2322: Type 'number' is not assignable to type 'string'.
Aturan praktis: biarkan TypeScript menebak untuk variabel lokal yang langsung diisi, dan tulis tipe secara eksplisit di batas: parameter function, nilai kembalian function publik, dan data dari luar. Ada juga perbedaan halus antara let dan const: const status = "aktif" bertipe literal "aktif" (karena tidak bisa diubah), sedangkan let status = "aktif" bertipe string.
Array dan tuple
Array ditulis tipe[] atau Array<tipe>. Keduanya sama; tim biasanya memilih satu gaya.
const nilai: number[] = [80, 90, 75];
const nama: Array<string> = ["Andi", "Budi"];
Tuple adalah array dengan panjang dan tipe per posisi yang tetap. Contoh paling akrab bagi developer React: useState mengembalikan tuple [nilai, fungsiPengubah].
const koordinat: [number, number] = [-6.2, 106.8]; // lintang, bujur
const entri: [string, number] = ["apel", 3];
Tuple boleh diberi label agar mudah dibaca: type Rentang = [awal: number, akhir: number];.
any vs unknown
Keduanya bisa menampung nilai apa pun. Bedanya ada di apa yang boleh kamu lakukan sesudahnya:
any |
unknown |
|
|---|---|---|
| Boleh diisi apa saja | Ya | Ya |
Boleh langsung dipakai (x.toUpperCase()) |
Ya, tanpa diperiksa | Tidak, harus dipersempit dulu |
| Keamanan | Mematikan pemeriksaan | Aman |
| Kapan dipakai | Darurat, migrasi sementara | Data dari luar: JSON.parse, catch (err), respons API |
Analogi: any itu seperti kotak tanpa label yang langsung kamu tuang ke masakan. unknown itu kotak tanpa label yang harus kamu cium dan cicipi dulu sebelum dipakai. Di mode strict, variabel err di catch (err) bertipe unknown, bukan any.
void dan never
void: function yang tidak mengembalikan nilai berguna, misalnya event handler atauconsole.log.never: sesuatu yang tidak pernah terjadi. Function yang selalu melempar error atau loop tanpa akhir mengembalikannever. Ia juga muncul ketika semua kemungkinan sudah habis dipersempit, dan dipakai untuk exhaustive check (modul Union & Narrowing).
null dan undefined di mode strict
Dengan strictNullChecks (bagian dari strict), null dan undefined bukan anggota otomatis tipe lain. let nama: string = null adalah error. Kalau sebuah nilai memang boleh kosong, katakan secara jujur: string | null. Ini yang membuat TypeScript bisa memperingatkan possibly 'undefined'.
Type assertion (as) secukupnya
nilai as Tipe berarti "percayalah, saya tahu tipenya". TypeScript tidak memeriksa kebenarannya di runtime. Pakai seminimal mungkin; lebih baik persempit dengan pemeriksaan sungguhan.
Contoh kode
// tipe-dasar.ts
// 1. Primitif dengan inferensi
let namaToko = "Warung Sari"; // string
let jumlahMeja = 12; // number
let buka = true; // boolean
const kategori = "kuliner"; // tipe literal "kuliner" karena const
namaToko = "Warung Sari Rasa"; // boleh, masih string
jumlahMeja = "dua belas"; // ❌ error TS2322: Type 'string' is not assignable to type 'number'.
// 2. Array dan tuple
const hargaMenu: number[] = [15000, 20000, 18000];
hargaMenu.push("gratis"); // ❌ error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.
const lokasi: [kota: string, kodePos: number] = ["Bandung", 40115];
const [kota, kodePos] = lokasi;
console.log(kota.toUpperCase(), kodePos.toFixed(0)); // → BANDUNG 40115
// 3. void
function catat(pesan: string): void {
console.log(`[LOG] ${pesan}`);
}
catat(`${namaToko} buka: ${buka}`); // → [LOG] Warung Sari Rasa buka: true
// 4. never: function yang tidak pernah selesai normal
function gagal(pesan: string): never {
throw new Error(pesan);
}
// 5. null secara jujur
let mejaDipesan: number | null = null;
mejaDipesan = 5;
console.log(kategori, mejaDipesan); // → kuliner 5
Sekarang perbandingan any dan unknown dengan data yang tidak jelas asalnya:
// any-vs-unknown.ts
const teksJson = '{"nama":"Sari","umur":25}';
// Dengan any: tidak ada pemeriksaan, typo pun lolos
const dataAny: any = JSON.parse(teksJson);
console.log(dataAny.nmae); // → undefined (tidak ada yang memperingatkan)
// Dengan unknown: dipaksa memeriksa dulu
const dataUnknown: unknown = JSON.parse(teksJson);
console.log(dataUnknown.nama); // ❌ error TS18046: 'dataUnknown' is of type 'unknown'.
if (
typeof dataUnknown === "object" &&
dataUnknown !== null &&
"nama" in dataUnknown &&
typeof dataUnknown.nama === "string"
) {
console.log(dataUnknown.nama.toUpperCase()); // → SARI
}
// catch (err) bertipe unknown di mode strict
try {
JSON.parse("{rusak");
} catch (err) {
const pesan = err instanceof Error ? err.message : String(err);
console.log("Gagal parse:", pesan);
}
Pemeriksaan manual seperti di atas memang panjang. Kabar baiknya, di modul Data API kamu akan memakai Zod untuk melakukan pemeriksaan ini dalam satu baris.
Kesalahan umum
- Menulis tipe berlebihan untuk hal yang sudah jelas.
const total: number = 5 + 3tidak salah, tapi berisik. Biarkan inferensi bekerja untuk variabel lokal; fokuskan anotasi di parameter dan batas data. - Memakai
String,Number,Boolean(kapital) sebagai tipe. Pakai huruf kecil:string,number,boolean. - Memakai
anyuntuk data dari luar. Pakaiunknownlalu persempit atau validasi.any"menular": hasil operasi padaanyjugaany. - Membuat array kosong tanpa tipe.
const daftar = []lalu diisi belakangan bisa membuat tipe yang tidak kamu inginkan. Tulisconst daftar: string[] = []. - Menyalahgunakan
as.const user = data as Userhanya membungkam compiler. Kalaudataternyata bukanUser, bug tetap muncul di runtime.
Latihan
- Mudah, Deklarasikan variabel untuk nama siswa, nilai ujian, dan status lulus tanpa menulis tipe. Arahkan kursor (hover) di editor untuk melihat tipe hasil inferensi. Lalu buat array
nilaiKelasbertipenumber[]. - Sedang, Buat tuple
RGBberisi tiga angka dan functionkeHex(warna: RGB): stringyang mengubahnya menjadi string seperti#ff8800. - Menantang, Tulis function
ambilAngka(input: unknown): numberyang mengembalikan angka kalauinputbertipe number, mengubah string berisi angka (misalnya"42") menjadi number, dan melempar error untuk kasus lain.
Lihat solusi
// 1. Mudah
let namaSiswa = "Dewi"; // string
let nilaiUjian = 88; // number
let lulus = nilaiUjian >= 75; // boolean
const nilaiKelas: number[] = [88, 70, 95];
console.log(namaSiswa, nilaiUjian, lulus, nilaiKelas.length); // → Dewi 88 true 3
// 2. Sedang
type RGB = [merah: number, hijau: number, biru: number];
function keHex(warna: RGB): string {
return "#" + warna.map((n) => n.toString(16).padStart(2, "0")).join("");
}
console.log(keHex([255, 136, 0])); // → #ff8800
// 3. Menantang
function ambilAngka(input: unknown): number {
if (typeof input === "number") return input;
if (typeof input === "string" && input.trim() !== "" && !Number.isNaN(Number(input))) {
return Number(input);
}
throw new Error(`Bukan angka: ${String(input)}`);
}
console.log(ambilAngka(7)); // → 7
console.log(ambilAngka("42")); // → 42
// ambilAngka("abc") → melempar Error: Bukan angka: abc
Ringkasan
- Tipe primitif:
string,number,boolean,bigint,symbol,null,undefined(huruf kecil). - TypeScript menebak tipe dari nilai awal; tulis tipe eksplisit di parameter, nilai kembalian publik, dan data dari luar.
- Array
T[]untuk daftar sejenis; tuple[A, B]untuk panjang dan posisi tetap. unknownaman untuk data tak dikenal karena wajib dipersempit dulu;anymematikan pemeriksaan.voiduntuk function tanpa nilai kembalian berguna;neveruntuk hal yang tidak pernah terjadi.