Mapped type, bir anahtar kümesi üzerinde dönerek yeni bir nesne tipi oluşturur. { [K in keyof T]: boolean }, "T tipinin her K anahtarı için, boolean tipinde K adlı bir özellik" anlamına gelir:
Features tipine bir anahtar ekleyin, Flags<Features> de onu ister. Mapped type'lar yalnızca derleme zamanında vardır: nesneleri tarif ederler, onları oluşturmazlar.
Sözdizimi
Bir mapped type'ın üç parçası vardır: bir anahtar değişkeni, üzerinde dönülecek bir anahtar union'ı ve anahtar değişkenini kullanabilen özellik tipi.
type MappedType = {
[K in Keys]: PropertyType; // K takes each member of Keys in turn
};
Keys herhangi bir string, number veya symbol union'ı olabilir. keyof üzerinden gelmesi gerekmez:
Record<Size, number> tam olarak bunu yapar; Record tek satırlık bir mapped type'tır. Özellik tipi anahtarı kullanabilir: { [K in keyof T]: T[K] } her özellik tipini bir indeksli erişimle olduğu gibi kopyalar, { [K in keyof T]: T[K] | null } ise her özelliği nullable yapar.
Belirleyiciler: +/- ile readonly ve ?
Bir mapped type, readonly ve opsiyonel (?) belirleyicilerini tüm özelliklere aynı anda ekleyebilir ya da onlardan kaldırabilir. Eklemek için başına + (hiçbir şey yazmadığınızda varsayılan budur), kaldırmak için - koyun:
Son satır, readonly belirleyicisinin yalnızca bir derleme zamanı kuralı olduğunu gösteriyor: atama bildirildi (ve burada @ts-expect-error ile bastırıldı), ama üretilen JavaScript onu yine de çalıştırdı. -? soru işaretini düşürmekten fazlasını yapar: özellik tipinden undefined değerini de çıkarır; bu yüzden AllRequired<Account>, { id: 1, email: undefined } değerini error TS2322: Type 'undefined' is not assignable to type 'string' ile reddeder.
Partial, Readonly, Pick ve Record Nasıl Yazılmıştır
Nesneleri yeniden biçimlendiren yerleşik yardımcı tipler mapped type'tır. Bunlar TypeScript'in kendi lib.es5.d.ts dosyasındaki tanımlardır:
type Partial<T> = { [P in keyof T]?: T[P] };
type Required<T> = { [P in keyof T]-?: T[P] };
type Readonly<T> = { readonly [P in keyof T]: T[P] };
type Pick<T, K extends keyof T> = { [P in K]: T[P] };
type Record<K extends keyof any, T> = { [P in K]: T };
Onları okumak iyi bir alıştırmadır: Pick yalnızca geçirdiğiniz anahtarlar üzerinde döner, Record ise herhangi bir kaynak tipi yok sayar ve her anahtara aynı değer tipini verir. Omit kendi başına bir mapped type değildir: Pick<T, Exclude<keyof T, K>> ifadesidir. Yardımcı tipler referansı hepsini listeliyor.
as ile Anahtar Yeniden Eşleme
Anahtardan sonra gelen bir as ifadesi özellik adını değiştirir. Template literal tiplerle birleştirildiğinde eski adlardan yeni adlar üretebilir:
string & K orada, çünkü keyof T, number ve symbol anahtarlar içerebilir ve Capitalize yalnızca string kabul eder. Intersection, string anahtarları tutar ve gerisini atar.
never ile Anahtarları Filtrelemek
as ifadesi bir anahtar için never üretirse o anahtar kaldırılır. Bir koşullu tiple, özellikleri tiplerine göre tutabilir ya da atabilirsiniz:
DataOnly gibi tipler, JSON.stringify sonrasında neyin kaldığını ya da bir formun neyi düzenlediğini tarif etmek için işe yarar: metotlar olmadan alanlar.
Hangi Belirleyiciler Korunur
Bir T tipi için keyof T üzerinden yazılan bir mapped type'a homomorfik denir ve her özelliğin readonly ve ? belirleyicilerini T tipinden kopyalar. Düz bir anahtar union'ı üzerinden yazılan bir mapped type ise hiç belirleyiciyle başlamaz:
type Account = { readonly id: number; email?: string };
type Copy<T> = { [K in keyof T]: T[K] };
type A = Copy<Account>;
// { readonly id: number; email?: string } (modifiers kept)
type B = { [K in "id" | "email"]: Account[K] };
// { id: number; email: string | undefined } (email is required now)
B tipinde email hâlâ undefined içerir, çünkü Account["email"] onu içerir; ama özelliğin kendisi artık opsiyonel değildir: { id: 1 } reddedilir. Partial<T> ve benzerlerinin keyof T üzerinden eşleme yapmasının nedeni budur: açıkça değiştirmedikleri her şeyi korurlar.
Bir diziye ya da tuple'a uygulanan generic homomorfik bir mapped type, sayısal anahtarlı bir nesne değil, bir dizi ya da tuple üretir. Readonly<string[]>, readonly string[] olur; type Box<T> = { [K in keyof T]: { value: T[K] } } ile de Box<[string, number]>, [{ value: string }, { value: number }] olur.
Mapped Type'lar ve Çalışma Zamanı Kodu
Bir mapped type yalnızca bir nesneyi tarif ettiği için, böyle bir nesne oluşturan bir fonksiyonun kendi çalışma zamanı döngüsüne ihtiyacı vardır. Tip ise onun sonucunu tarif eder:
Callback'ler parametre tiplerini hiçbir notasyon olmadan mapped type'tan alır (v birinde string, diğerinde number olur). Buraya tip eşleme yerine Map sınıfını aramak için geldiyseniz TypeScript'te Map sayfasına bakın.
Sıkça Sorulan Sorular
TypeScript'te mapped type nedir?
Bir anahtar union'ı üzerinde dönerek bir nesne tipi oluşturan tiptir: { [K in Keys]: SomeType }. Anahtarlar çoğunlukla keyof T olur; böylece yeni tip, type Flags<T> = { [K in keyof T]: boolean } örneğindeki gibi, T ile aynı anahtarlara ve dönüştürülmüş özellik tiplerine sahip olur.
Bir mapped type'ta +readonly, -readonly, +? ve -? ne anlama gelir?
Belirleyici ekler ya da kaldırırlar. readonly veya +readonly her özelliği readonly yapar, -readonly readonly'yi kaldırır. ? veya +? her özelliği opsiyonel yapar, -? ise onları zorunlu yapar ve tiplerinden undefined değerini de çıkarır. Required<T>, -? ile yazılmıştır.
Bir mapped type'ta anahtarları nasıl yeniden adlandırırım?
Anahtardan sonra bir as ifadesi kullanın: { [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K] }, name anahtarını getName yapar. as ifadesinde bir anahtarı never olarak eşlemek onu kaldırır; özellikleri filtrelemenin yolu budur.
Mapped type, TypeScript'teki Map ile aynı şey midir?
Hayır. Mapped type, derleme zamanında yapılan bir tip dönüşümüdür ve hiç kod üretmez. Map<K, V> ise JavaScript'in Map sınıfıdır, anahtar değer çiftlerinden oluşan bir çalışma zamanı koleksiyonudur. "typescript map type" aramaları çoğu zaman ikisinden birini kasteder.
Partial ve Readonly nasıl implement edilmiştir?
Standart kütüphanede mapped type olarak: type Partial<T> = { [P in keyof T]?: T[P] } ve type Readonly<T> = { readonly [P in keyof T]: T[P] }. Pick ve Record da mapped type'tır; Omit ise Pick ile Exclude birleşimidir.