keyof, typeof & Indexed Access Types
Menurunkan tipe dari nilai dengan typeof, mengambil daftar kunci dengan keyof, membaca tipe properti dengan T[K], dan pola praktis dari konfigurasi dan daftar konstan.
Tiga perkakas untuk "bertanya" pada tipe
Bab ini mengajarkan tiga operator yang membuat tipe mengikuti kode yang sudah ada, bukan ditulis ganda: typeof (tipe dari sebuah nilai), keyof (daftar kunci dari sebuah tipe), dan T[K] (tipe sebuah properti).
typeof di posisi tipe
JavaScript sudah punya typeof yang menghasilkan teks saat runtime. Di TypeScript, jika typeof dipakai di tempat yang menunggu tipe, ia menghasilkan tipe dari sebuah variabel:
const konfigurasi = {
host: "localhost",
port: 3000,
debug: true,
}
type Konfigurasi = typeof konfigurasi
// { host: string; port: number; debug: boolean }
function mulai(k: Konfigurasi) { /* ... */ }
Kalau suatu hari kamu menambah properti ke konfigurasi, Konfigurasi otomatis ikut. Cocok untuk object konstan, hasil fungsi (typeof fungsi), dan class (typeof NamaClass).
keyof: gabungan semua nama properti
type Kunci = keyof Konfigurasi // "host" | "port" | "debug"
function bacaKunci(k: Kunci) { return konfigurasi[k] }
bacaKunci("port") // ✅
bacaKunci("timeout") // ❌ Argument of type '"timeout"' is not assignable...
interface Produk { id: number; nama: string }
type KunciProduk = keyof Produk // "id" | "nama"
Dengan keyof, daftar kunci tidak perlu ditulis manual — editor menawarkannya di autocomplete.
Indexed access: T[K]
Mengambil tipe sebuah properti, mirip membaca nilai dengan kurung siku:
type TipePort = Konfigurasi["port"] // number
type TipeBebas = Konfigurasi["host" | "debug"] // string | boolean
type SemuaNilai = Konfigurasi[keyof Konfigurasi] // string | number | boolean
interface Respons {
data: { id: number; judul: string }[]
total: number
}
type SatuItem = Respons["data"][number] // { id: number; judul: string } — elemen array!
Trik [number] pada array/tuple mengambil tipe elemennya. Ini sering dipakai untuk memecah tipe dari struktur bersarang, terutama hasil API.
Menggabungkan: fungsi pembaca yang aman
function baca<K extends keyof Konfigurasi>(kunci: K): Konfigurasi[K] {
return konfigurasi[kunci]
}
const p = baca("port") // number
const h = baca("host") // string
const d = baca("debug") // boolean
Tipe hasil menyesuaikan kunci yang diminta. Ini fondasi dari hampir semua pustaka bertipe aman (mis. getItem, get(key), atau pemilih state).
Pola: daftar konstan → tipe
Ingat as const dari bab 10:
const WARNA = ["merah", "hijau", "biru"] as const
type Warna = (typeof WARNA)[number] // "merah" | "hijau" | "biru"
const KODE = { ok: 200, tidakAda: 404 } as const
type NamaKode = keyof typeof KODE // "ok" | "tidakAda"
type NilaiKode = (typeof KODE)[NamaKode] // 200 | 404
function adalahWarna(x: string): x is Warna {
return (WARNA as readonly string[]).includes(x)
}
Satu sumber (array/object konstan) → daftar nilai untuk runtime dan tipe untuk compile time. Tidak ada lagi dua daftar yang bisa lupa disinkronkan.
Hati-hati: typeof dua dunia
| Konteks | Contoh | Hasil |
|---|---|---|
| Ekspresi (runtime) | typeof x === "string" | Teks "string" |
| Posisi tipe | type T = typeof x | Tipe dari x |
Kesalahan umum pemula
- Menulis
keyof Konfigurasipadahal maksudnya kunci dari nilai: butuhkeyof typeof konfigurasi(nilai harus lewattypeofdulu). - Mengakses
Tipe.propertidengan titik; yang benar di posisi tipe adalahTipe["properti"]. - Lupa
as constsehinggakeyof typeoftetap benar tetapi nilainya melebar jadistring.