İndeksli erişim tipi, JavaScript'in özellik erişimi için kullandığı köşeli parantez sözdizimiyle, başka bir tip üzerindeki bir özelliğin tipini arar. Person["age"], number tipidir; Person["address"]["city"] ise string tipidir.
Faydası tek bir doğruluk kaynağıdır. Age, number tipinin ikinci bir kopyası değildir: Person["age"] tipi string olarak değişirse, Person["age"] olarak yazılmış her tip de onunla birlikte değişir. İndeksli erişim tipleri yalnızca derleme zamanında vardır; hiç JavaScript üretmezler.
Union Anahtarlar ve T[keyof T]
İndeks bir anahtar union'ı olabilir. Sonuç, özellik tiplerinin union'ıdır:
Product[keyof Product], tip düzeyinde "Product'ın herhangi bir özellik değeri" demenin yoludur. Var olmayan bir anahtarı istemek bir derleme hatasıdır: Product["price"], error TS2339: Property 'price' does not exist on type 'Product' verir.
Opsiyonel Özellikler undefined İçerir
strictNullChecks açıkken (strict kapsamında açıktır), opsiyonel bir özelliğin tipi undefined içerir; indeksli erişim tipi de öyle:
type Profile = { name: string; nickname?: string };
type Nick = Profile["nickname"]; // string | undefined
undefined değerini çıkarmak için sarmalayın: NonNullable<Profile["nickname"]>, string olur.
T[number] ile Dizi Eleman Tipleri
Diziler sayılarla indekslenir, bu yüzden bir dizi tipini number ile indekslemek eleman tipini verir. Bu birkaç seviye boyunca da çalışır:
Bu, bir tip kontrol etmediğiniz bir yerden geldiğinde işe yarar, örneğin üretilmiş bir API istemcisinden: ApiResponse["data"]["users"][number], kimse dışa aktarmamış olsa bile kullanıcı tipine bir ad verir.
Tuple'lar: Konuma Göre İndeksleme
Bir tuple tipi belirli bir konumla, tüm eleman tiplerinin union'ı için number ile ve uzunluğunu literal bir tip olarak almak için "length" ile indekslenebilir:
(typeof arr)[number]: Bir const Diziden Union
Gerçek hayattaki en yaygın kullanım: izin verilen değerlerin listesini bir dizi olarak tutun (böylece çalışma zamanında üzerinde dönebilirsiniz) ve union tipini ondan türetin (böylece derleyici onu kontrol eder).
Bunu iki parça çalıştırır. as const, diziyi literal tiplerden oluşan readonly bir tuple yapar; o olmadan ROLES, string[] olur ve (typeof ROLES)[number] yalnızca string olur. Sonra typeof değeri bir tipe çevirir, [number] da elemanlarını bir union'da toplar. Parantezler isteğe bağlıdır (typeof ROLES[number] aynı anlama gelir), ama işlem sırasını netleştirir.
Bir String'i Diziye Karşı Kontrol Etmek
Bu readonly tuple'ın bir sürprizi var. includes metodu yalnızca eleman tipini kabul eder, bu yüzden ona rastgele bir string geçiremezsiniz:
index.ts(6,25): error TS2345: Argument of type 'string' is not assignable to parameter of type '"admin" | "editor" | "viewer"'.
Kontrol için diziyi readonly string[] olarak genişletin ve fonksiyonu bir type guard haline getirin ki başarılı bir kontrol değeri daraltsın:
Bu kalıp size iki iş için tek bir liste verir: çalışma zamanı kontrolü diziyi kullanır, tip de ondan türetilir; bu yüzden ikisi birbirinden kopamaz.
Generics'te İndeksli Erişim: T[K]
Bir generic içinde, K extends keyof T ile T[K], çağıranın seçtiği özellik hangisiyse onun tipidir:
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[]
T[K] ifadesini geçerli kılan şey K extends keyof T kısıtlamasıdır. O olmadan TypeScript K değerinin T tipinin bir anahtarı olduğunu bilemez ve error TS2536: Type 'K' cannot be used to index type 'T' bildirir.
Bir Bakışta Sözdizimi
| Yazılış | Anlamı | Örnek sonuç |
|---|---|---|
T["key"] | tek bir özelliğin tipi | Person["age"], number olur |
T["a" | "b"] | o özellik tiplerinin union'ı | string | number |
T[keyof T] | tüm özellik tiplerinin union'ı | her değer tipi |
T["a"]["b"] | iç içe özellik | Person["address"]["city"] |
Arr[number] | dizi eleman tipi | User[] sonucu User |
Tup[0] | bir konumdaki tuple elemanı | ilk elemanın tipi |
Tup["length"] | literal olarak tuple uzunluğu | 3 |
(typeof arr)[number] | bir const dizinin değerlerinin union'ı | "admin" | "editor" |
T[typeof key] | bir sabitin tipiyle indeksleme | T["name"] ile aynı |
İndeks her zaman bir tiptir. key bir const değişken iken Person[key] iki hatayla başarısız olur: error TS2538: Type 'key' cannot be used as an index type. ve error TS2749: 'key' refers to a value, but is being used as a type here. Did you mean 'typeof key'?.
Sıkça Sorulan Sorular
TypeScript'te indeksli erişim tipi nedir?
T tipi üzerindeki K özelliğinin tipini arayan, T[K] biçiminde yazılan bir tiptir. type Person = { name: string; age: number } ile Person["age"], number olur. JavaScript'teki özellik erişimiyle aynı köşeli parantez sözdizimini kullanır, ama derleme zamanında tipler üzerinde çalışır.
TypeScript'te bir dizi elemanının tipini nasıl alırım?
Dizi tipini number ile indeksleyin: type Users = User[] için Users[number], User olur. Bir dizi değeri için bunu typeof ile birleştirin: (typeof users)[number].
Bir string dizisini nasıl union tipine çeviririm?
Diziyi as const ile bildirin ki TypeScript literal değerleri korusun, ardından onu number ile indeksleyin: const roles = ["admin", "editor"] as const; type Role = (typeof roles)[number]; sonucu "admin" | "editor" olur. as const olmadan eleman tipi yalnızca string olur.
İndeksli erişim tipinde neden bir değişkeni indeks olarak kullanamıyorum?
İndeks bir tip olmalıdır. const key = "name" ile Person[key] başarısız olur (TS2538 ve TS2749 hataları), çünkü key bir değerdir. Person[typeof key] yazın ya da literal'i doğrudan kullanın: Person["name"].
T[keyof T] ne anlama gelir?
T tipini tüm anahtarlarının union'ı ile indeksler, bu yüzden sonuç tüm özellik tiplerinin union'ıdır. { a: string; b: number } için string | number olur. Tip düzeyinde "bu nesnenin herhangi bir değeri" demenin yoludur.