Menu

Indexed Access Type TypeScript: T[K], T[number], dan Lainnya

Indexed access type membaca tipe sebuah properti dari tipe lain: Person["age"] adalah number. Pelajari T["key"], key berupa union, T[keyof T], T[number] untuk elemen array, indeks tuple, dan (typeof arr)[number] untuk mengubah array const menjadi union.

Halaman ini dilengkapi editor yang bisa dijalankan. Edit, jalankan, dan lihat output-nya seketika.

Indexed access type mencari tipe sebuah properti pada tipe lain, dengan sintaks kurung siku yang sama seperti akses properti di JavaScript. Person["age"] adalah number, dan Person["address"]["city"] adalah string.

Keuntungannya adalah satu sumber kebenaran. Age bukan salinan kedua dari number: kalau Person["age"] berubah menjadi string, setiap tipe yang ditulis sebagai Person["age"] ikut berubah. Indexed access type hanya ada saat kompilasi; ia tidak menghasilkan kode JavaScript apa pun.

Key Berupa Union dan T[keyof T]

Indeksnya bisa berupa union dari beberapa key. Hasilnya adalah union dari tipe-tipe properti tersebut:

Product[keyof Product] adalah cara di level tipe untuk mengatakan "nilai properti apa pun dari Product". Meminta key yang tidak ada adalah error kompilasi: Product["price"] menghasilkan error TS2339: Property 'price' does not exist on type 'Product'.

Properti Opsional Mengandung undefined

Dengan strictNullChecks (aktif di bawah strict), tipe properti opsional mengandung undefined, begitu juga indexed access type-nya:

type Profile = { name: string; nickname?: string };

type Nick = Profile["nickname"]; // string | undefined

Untuk membuang undefined, bungkus tipenya: NonNullable<Profile["nickname"]> adalah string.

Tipe Elemen Array dengan T[number]

Array diberi indeks dengan angka, jadi memberi indeks number pada tipe array menghasilkan tipe elemennya. Ini juga bekerja melewati beberapa level:

Ini berguna kalau sebuah tipe berasal dari tempat yang tidak kamu kendalikan, misalnya API client yang di-generate: ApiResponse["data"]["users"][number] memberi nama pada tipe user tanpa ada yang perlu meng-export-nya.

Tuple: Indeks Berdasarkan Posisi

Tipe tuple bisa diberi indeks dengan posisi tertentu, dengan number untuk union dari semua tipe elemennya, dan dengan "length" untuk panjangnya sebagai tipe literal:

(typeof arr)[number]: Union dari Array const

Pemakaian yang paling sering di dunia nyata: simpan daftar nilai yang diizinkan sebagai array (supaya bisa di-loop saat runtime), lalu turunkan union type darinya (supaya compiler bisa memeriksanya).

Ada dua bagian yang membuatnya bekerja. as const membuat array menjadi tuple readonly berisi tipe literal; tanpanya, ROLES adalah string[] dan (typeof ROLES)[number] hanya string. Lalu typeof mengubah nilai menjadi tipe, dan [number] mengumpulkan elemen-elemennya menjadi union. Tanda kurungnya opsional (typeof ROLES[number] artinya sama), tetapi membuat urutan operasinya jelas.

Memeriksa String terhadap Array

Tuple readonly itu punya satu kejutan. Method includes-nya hanya menerima tipe elemen, jadi kamu tidak bisa mengirim string sembarang ke sana:

index.ts(6,25): error TS2345: Argument of type 'string' is not assignable to parameter of type '"admin" | "editor" | "viewer"'.

Lebarkan array menjadi readonly string[] untuk pemeriksaannya, lalu ubah fungsinya menjadi type guard agar pemeriksaan yang berhasil mempersempit tipe nilainya:

Pola ini memberimu satu daftar untuk dua tugas: pemeriksaan saat runtime memakai array, dan tipenya diturunkan dari array itu, jadi keduanya tidak bisa tidak sinkron.

Indexed Access di Generic: T[K]

Di dalam generic, T[K] dengan K extends keyof T adalah tipe dari properti mana pun yang dipilih pemanggil:

function pluck<T, K extends keyof T>(items: T[], key: K): T[K][] {
  return items.map((item) => item[key]);
}

const users = [
  { name: "Ada", age: 36 },
  { name: "Linus", age: 28 },
];

const names = pluck(users, "name"); // string[]
const ages = pluck(users, "age");   // number[]

Constraint K extends keyof T itulah yang membuat T[K] sah. Tanpanya, TypeScript tidak bisa tahu bahwa K adalah key dari T dan melaporkan error TS2536: Type 'K' cannot be used to index type 'T'.

Ringkasan Sintaks

DitulisArtinyaContoh hasil
T["key"]tipe satu propertiPerson["age"] adalah number
T["a" | "b"]union dari tipe-tipe properti itustring | number
T[keyof T]union dari semua tipe propertisetiap tipe nilai
T["a"]["b"]properti bersarangPerson["address"]["city"]
Arr[number]tipe elemen arrayUser[] menghasilkan User
Tup[0]elemen tuple pada suatu posisitipe elemen pertama
Tup["length"]panjang tuple sebagai literal3
(typeof arr)[number]union dari nilai-nilai array const"admin" | "editor"
T[typeof key]indeks dengan tipe sebuah konstantasama dengan T["name"]

Indeksnya selalu berupa tipe. Person[key] dengan key adalah variabel const gagal dengan dua error: error TS2538: Type 'key' cannot be used as an index type. dan error TS2749: 'key' refers to a value, but is being used as a type here. Did you mean 'typeof key'?.

Pertanyaan yang sering diajukan

Apa itu indexed access type di TypeScript?

Tipe yang ditulis T[K] untuk mencari tipe properti K pada tipe T. Dengan type Person = { name: string; age: number }, Person["age"] adalah number. Sintaks kurung sikunya sama dengan akses properti di JavaScript, tetapi bekerja pada tipe saat kompilasi.

Bagaimana cara mendapatkan tipe elemen array di TypeScript?

Beri indeks number pada tipe array-nya: untuk type Users = User[], Users[number] adalah User. Untuk nilai array, gabungkan dengan typeof: (typeof users)[number].

Bagaimana cara mengubah array string menjadi union type?

Deklarasikan array dengan as const agar TypeScript mempertahankan nilai literalnya, lalu beri indeks number: const roles = ["admin", "editor"] as const; type Role = (typeof roles)[number]; menghasilkan "admin" | "editor". Tanpa as const, tipe elemennya hanya string.

Kenapa variabel tidak bisa dipakai sebagai indeks pada indexed access type?

Indeksnya harus berupa tipe. Person[key] dengan const key = "name" gagal (error TS2538 dan TS2749) karena key adalah sebuah nilai. Tulis Person[typeof key], atau pakai literalnya langsung: Person["name"].

Apa arti T[keyof T]?

Ini memberi indeks pada T dengan union dari semua key-nya, jadi hasilnya adalah union dari semua tipe propertinya. Untuk { a: string; b: number }, hasilnya string | number. Ini cara di level tipe untuk mengatakan "nilai apa pun dari object ini".

Ilustrasi bahasa pemrograman di Coddy

Belajar coding dengan Coddy

Mulai