TypeScript'te keyof bir nesne tipinin anahtarlarını string ya da sayı literal union'ı olarak verir, typeof (tip konumunda) bir değişkenin tipini yakalar, indexed access tipi T["alan"] ise bir tipin belirli bir özelliğinin tipini okur. Üçü birlikte kullanıldığında, bir sabit nesneden ya da diziden tipleri elle tekrar yazmadan türetebilirsiniz.
Bu yazıda üç operatörü ayrı ayrı ve birlikte, TypeScript 6.0 ile derlenmiş örneklerle anlatıyoruz. Bu operatörler generics, mapped types ve conditional types için temel yapı taşıdır; TypeScript ileri seviye özeti bu konuların kısa bir özetini verir.
keyof tip operatörü
keyof bir nesne tipini alır ve anahtarlarından oluşan bir literal union üretir:
type Nokta = { x: number; y: number };
type N = keyof Nokta; // "x" | "y"
interface Kullanici {
id: number;
ad: string;
aktif: boolean;
}
type Alan = keyof Kullanici; // keyof Kullanici, yani "id" | "ad" | "aktif"
const a: Alan = "ad"; // geçerli
const b: Alan = "soyad";
// TS2322: Type '"soyad"' is not assignable to type 'keyof Kullanici'.Tipin bir index signature'ı varsa keyof literal anahtarlar yerine o anahtar tipini döndürür. Burada çoğu kişiyi şaşırtan bir ayrıntı var: string index signature için sonuç string | number olur. Sebebi, JavaScript'te nesne anahtarlarının her zaman string'e dönüştürülmesidir; obj[0] ile obj["0"] aynı şeydir.
type Diziye = { [n: number]: unknown };
type A = keyof Diziye; // number
type Sozluk = { [k: string]: boolean };
type M = keyof Sozluk; // string | numberkeyof asıl gücünü generic kısıtlarda gösterir. K extends keyof T kalıbıyla yalnızca var olan anahtarları kabul eden fonksiyonlar yazabilirsiniz; bu kalıbı generics yazımızda örnekledik.
typeof tip operatörü

JavaScript'teki typeof bir ifade operatörüdür ve çalışma anında "string", "number" gibi bir metin döndürür. TypeScript, aynı anahtar kelimeyi tip konumunda da kullanmanıza izin verir; orada bir değişkenin ya da özelliğin derleme zamanındaki tipini verir. İki kullanım birbirinden tamamen farklıdır:
let s = "merhaba";
console.log(typeof s); // string (JavaScript, çalışma anı)
let n: typeof s; // string (TypeScript, tip konumu)
const sabit = "merhaba";
type Sabit = typeof sabit; // "merhaba"const ile tanımlanan bir string'in tipi literal "merhaba" olarak kalır, let ile tanımlanan genişler. Bu genişleme davranışı ve as const için literal tipler ve as const yazımıza bakabilirsiniz.
typeof ile yapılandırma nesnesinden tip
Pratikte typeof en çok, zaten yazılmış bir nesneden tip üretmek için kullanılır. Böylece tip ve değer tek yerde tanımlanır, birbirinden kopamaz:
const varsayilanAyar = {
port: 3000,
host: "localhost",
gunluk: { seviye: "info", dosya: false },
};
type Ayar = typeof varsayilanAyar;
// { port: number; host: string; gunluk: { seviye: string; dosya: boolean; }; }
function baslat(ayar: Ayar) {
console.log(`${ayar.host}:${ayar.port}`);
}
baslat(varsayilanAyar); // localhost:3000Değer ile tip karışınca: TS2749
ReturnType gibi yerleşik tipler bir tip bekler. Bir fonksiyonun adını doğrudan verirseniz derleyici, değeri tip yerine kullandığınızı söyler ve typeof önerir:
function konum() {
return { x: 10, y: 3 };
}
type P1 = ReturnType<konum>;
// TS2749: 'konum' refers to a value, but is being used as a type here. Did you mean 'typeof konum'?
type P2 = ReturnType<typeof konum>; // { x: number; y: number; }typeof'un sınırı
TypeScript, typeof'u bilerek kısıtlar: yalnızca tanımlayıcılar (değişken adları) ve onların özellikleri üzerinde kullanılabilir. Bir fonksiyon çağrısının sonucunun tipini typeof f() ile alamazsınız; bunun amacı, çalıştığını sandığınız ama aslında çalışmayan kod yazmanızı önlemektir. Çağrı sonucunun tipi için ReturnType<typeof f> kullanın.
declare const onayla: (soru: string) => boolean;
let devam: typeof onayla("Emin misiniz?");
// TS1005: ',' expected.
let devam2: ReturnType<typeof onayla>; // booleanIndexed access tipleri: T["alan"]
Indexed access tipi, köşeli parantez sözdizimiyle bir tipin belirli bir özelliğinin tipini okur. Parantezin içindeki şey de bir tiptir; bu yüzden union, keyof veya bir type alias kullanabilirsiniz:
type Kisi = { yas: number; ad: string; hayatta: boolean };
type Yas = Kisi["yas"]; // number
type I1 = Kisi["yas" | "ad"]; // string | number
type I2 = Kisi[keyof Kisi]; // string | number | boolean
type AdVeyaHayatta = "hayatta" | "ad";
type I3 = Kisi[AdVeyaHayatta]; // string | boolean
type Hatali = Kisi["yass"];
// TS2339: Property 'yass' does not exist on type 'Kisi'.Kisi[keyof Kisi] kalıbı, bir nesnenin tüm değer tiplerinin union'ını verir ve sık kullanılır. Olmayan bir özelliği okumaya çalışırsanız derleme hatası alırsınız; bu da yazım hatalarını erkenden yakalar.
Dizi elemanının tipi: T[number]
Indeks olarak number kullanmak bir dizinin eleman tipini verir. typeof ile birleştirince bir dizi literalinden eleman tipini çıkarabilirsiniz:
const kullanicilar = [
{ ad: "Ali", yas: 15 },
{ ad: "Zeynep", yas: 23 },
];
type Kullanici = typeof kullanicilar[number]; // { ad: string; yas: number; }
type Yas = typeof kullanicilar[number]["yas"]; // numberAynı teknik as const ile birleştiğinde, bir sabit listeden union tipi üretmenin en yaygın yoludur. Liste değişince tip de kendiliğinden güncellenir:
const ROLLER = ["yonetici", "editor", "okur"] as const;
type Rol = typeof ROLLER[number]; // "yonetici" | "editor" | "okur"
function yetkiVer(rol: Rol) {
return ROLLER.indexOf(rol);
}
console.log(yetkiVer("editor")); // 1Indeks olarak değer kullanılamaz
Köşeli parantezin içine yalnızca tip yazılabilir. Bir const değişkeni kullanırsanız iki hata birden alırsınız; çözüm, aynı değeri bir type alias olarak tanımlamaktır:
type Kisi = { yas: number; ad: string };
const anahtar = "yas";
type Y1 = Kisi[anahtar];
// TS2538: Type 'anahtar' cannot be used as an index type.
// TS2749: 'anahtar' refers to a value, but is being used as a type here. Did you mean 'typeof anahtar'?
type Anahtar = "yas";
type Y2 = Kisi[Anahtar]; // number
type Y3 = Kisi[typeof anahtar]; // numberÜçü birlikte: keyof typeof kalıbı
Gerçek projelerde en sık göreceğiniz birleşim keyof typeof nesne kalıbıdır. Önce typeof ile nesnenin tipini alır, sonra keyof ile anahtarlarını union'a çevirirsiniz. Indexed access de değer tipini verir:
const RENKLER = {
kirmizi: "#ff0000",
yesil: "#00ff00",
mavi: "#0000ff",
} as const;
type Renk = keyof typeof RENKLER; // "kirmizi" | "yesil" | "mavi"
type Hex = (typeof RENKLER)[Renk]; // "#ff0000" | "#00ff00" | "#0000ff"
function renkKodu(r: Renk): Hex {
return RENKLER[r];
}
console.log(renkKodu("yesil")); // #00ff00Karşılaştırma tablosu
![Karşılaştırma tablosu: typeof x (JavaScript), typeof x (TypeScript), keyof T, T["alan"]](/assets/blog/typescript-keyof-typeof-indexed-access-b5.webp)
| Sözdizimi | Nerede | Ne verir | Örnek sonuç |
|---|---|---|---|
| typeof x (JavaScript) | İfade, çalışma anı | Tip adını string olarak | "string" |
| typeof x (TypeScript) | Tip konumu | x değişkeninin tipi | string |
| keyof T | Tip konumu | T anahtarlarının union'ı | "x" | "y" |
| T["alan"] | Tip konumu | Bir özelliğin tipi | number |
| T[keyof T] | Tip konumu | Tüm değer tiplerinin union'ı | string | number |
| T[number] | Tip konumu | Dizi eleman tipi | { ad: string } |
| keyof typeof obj | Tip konumu | Bir değerin anahtar union'ı | "kirmizi" | "yesil" |
Sık yapılan hatalar
Object.keys sonucunu anahtar sanmak
Standart kütüphane tanımında Object.keys string[] döndürür, (keyof T)[] değil. Bu yüzden döngüde gelen anahtarla nesneyi indekslemek strict modda hata verir:
const fiyat = { cay: 20, kahve: 45 };
for (const k of Object.keys(fiyat)) {
console.log(fiyat[k]);
// TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ cay: number; kahve: number; }'.
// No index signature with a parameter of type 'string' was found on type '{ cay: number; kahve: number; }'.
}Nesne yapısal tiplendiği için çalışma anında beklediğinizden fazla anahtar taşıyabilir; string[] tanımının sebebi budur. Anahtarların gerçekten sabit olduğundan eminseniz Object.entries ile değerlere doğrudan ulaşmak ya da anahtarı keyof typeof fiyat tipine bilinçli olarak dönüştürmek seçeneklerinizdir. Dönüşümün riskleri için type assertion yazımıza bakın.
keyof'u değere uygulamak
keyof yalnızca tiplere uygulanır. keyof RENKLER yazarsanız TS2749 hatası alırsınız; doğrusu keyof typeof RENKLER.
Genişlemiş tipleri beklemek
as const olmadan typeof ROLLER[number] size string verir, union değil. Literal tip istiyorsanız diziyi ya da nesneyi as const ile tanımlayın.
Sık Sorulan Sorular
keyof neden bazen string | number döndürüyor?
Tipin bir string index signature'ı varsa keyof sonucu string | number olur, çünkü JavaScript sayısal anahtarları da string'e çevirir. Bunu değiştiren eski seçenek TypeScript 6.0'da tamamen kaldırıldı.
typeof bir tipe uygulanabilir mi?
Hayır. Tip konumundaki typeof bir değerin tipini alır. Zaten bir tipiniz varsa doğrudan onu kullanırsınız.
T["a"]["b"] gibi zincirleme okuma yapabilir miyim?
Evet. Indexed access tipleri zincirlenebilir; typeof kullanicilar[number]["yas"] örneğinde olduğu gibi her adım bir önceki sonucun içine iner.
Bu operatörler JavaScript çıktısında görünür mü?
Tip konumundaki keyof, typeof ve indexed access tamamen derleme zamanına aittir ve çıktıdan silinir. Yalnızca ifade konumundaki typeof JavaScript'in kendi operatörüdür; onun davranışını JavaScript veri tipleri yazımızda bulabilirsiniz.
Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.
İlgili içerikler: TypeScript öğrenme rehberi · Generics · Mapped types · Literal tipler ve as const · Utility types · TypeScript ileri seviye özeti