TYPESCRIPT GENERICS VE CONDITIONAL TYPES
Fonksiyon parametresine any yazdığınız an derleyici susuyor, IDE öneri vermiyor, runtime'da bir gün beklenmedik bir undefined ile karşılaşıyorsunuz. Tipler dosyada yazıyor görünüyor ama aslında hiçbir şey doğrulanmıyor — TypeScript'in tüm vaadi bu satırda buharlaşıyor. Çözüm any'yi yasaklamak değil, onu yazdığınız yerlerin çoğunda aslında bir generic parametre veya conditional type istediğinizi fark etmek.
any Neden Tip Güvenliğini Çökertir?
any, tipi bilinmeyen bir değer için değil, tip kontrolünü kapatmak için kullanılır. Derleyici bu değerle yapılan her işlemi onaylar: alanına eriştiniz mi var sayar, fonksiyon olarak çağırdınız mı çağrılabilir sayar. Aşağıdaki kod hatasız derlenir ama çalıştığında çöker:
function getFirst(items: any) {
return items[0].name.toUpperCase();
}
getFirst(42); // derleyici sessiz, runtime patlarProblem şu: yazar aslında "bu fonksiyon herhangi bir dizi alır ve içindeki öğelerden birini döner" demek istiyordu. Bunu söyleyebileceği bir araç vardı — sadece kullanmadı. Konuya ilişkin geniş kapsamlı belgeleri ek bir başvuru kaynağı olarak değerlendirilebilir.
Generic Parametre: Tipi Çağıran Söylesin
Generic parametre, bir fonksiyon veya tip tanımına "bu kısmı çağıran kod doldursun" boşluğu açar. Yukarıdaki örneğin tip-güvenli hali:
function getFirst<T>(items: T[]): T {
return items[0];
}
const user = getFirst([{ name: "Ada" }, { name: "Lin" }]);
// user: { name: string }T, çağrıldığı yerden çıkarımla doldurulur. Artık getFirst(42) derlenmez çünkü 42 bir T[] değildir. Generic'ler sadece dizi için değil, neredeyse her "içeriği değişen kap" için kullanılır:
- Constraint ile sınırlama:
<T extends { id: string }>diyerek T'nin en azından id alanı taşımasını şart koşarsınız. - Birden fazla parametre:
map<Input, Output>(arr: Input[], fn: (x: Input) => Output): Output[]hem girişi hem çıkışı izler. - Varsayılan değer:
<T = string>ile çağıran açıkça yazmazsa kullanılacak tip belirlenir. - Çağrı sitesinde manuel verme:
getFirst<User>(data)şeklinde çıkarımı geçersiz kılabilirsiniz.
Bu mekanizmaların derinine inmek için TypeScript eğitimi içeriğinden yararlanabilirsiniz; özellikle generic constraint ve keyof kombinasyonu pratikte sık karşınıza çıkacaktır.

Conditional Type: Tipe Göre Tip Üret
Generic'ler "tipi dışarıdan al" der; conditional type ise "aldığın tipe göre farklı bir tip dön" der. Sözdizimi terner ifadeye benzer: T extends U ? X : Y.
type Unwrap<T> = T extends Promise<infer U> ? U : T;
type A = Unwrap<Promise<string>>; // string
type B = Unwrap<number>; // numberinfer U, koşulun sol tarafındaki bir alt-tipi yakalayıp sağ tarafta kullanmaya yarar. Bu sayede any'ye düşmeden, gelen tipi soyup içindeki gerçek değeri ortaya çıkarırsınız.
Distributive Conditional Types
Conditional type, union üzerinde çalıştırıldığında her elemana ayrı ayrı uygulanır:
type NonNull<T> = T extends null | undefined ? never : T;
type Clean = NonNull<string | null | number>; // string | numberBu davranış Exclude, Extract, NonNullable gibi standart utility'lerin temelidir.
Pratik Senaryo: API İstemcisi
Diyelim ki bir HTTP istemcisi yazıyorsunuz. Endpoint adına göre dönen tip değişiyor. any ile yazılsa şöyle olur:
function request(endpoint: string): any { /* ... */ }
const u = request("/users/1"); // u: any, hiçbir koruma yokÖnce endpoint-tip eşleşmesini bir map ile modelleyin, sonra generic ve conditional type'ı birleştirin:
type Routes = {
"/users/1": { id: number; name: string };
"/products": { sku: string; price: number }[];
};
function request<K extends keyof Routes>(endpoint: K): Promise<Routes[K]> {
return fetch(endpoint).then(r => r.json());
}
const u = await request("/users/1");
// u: { id: number; name: string }Artık endpoint adını yanlış yazarsanız derleme hatası alırsınız, dönen değerin alanları otomatik tamamlanır, refaktör güvenli hale gelir.
Ne Zaman Hangisi?
- Generic parametre: Fonksiyon ya da sınıf, içeriği bilmeden çalışacak şekilde tasarlanıyorsa.
- Conditional type: Gelen tipe bakıp farklı çıkış tipi üretmek gerekiyorsa.
- infer: Mevcut bir tipin içinden bir parçayı ayıklamak gerekiyorsa (örn.
ReturnType,Parameters). - Mapped type ile kombinasyon: Bir nesnenin tüm alanlarını koşullu olarak dönüştürmek gerekiyorsa.
Sık Karşılaşılan Tuzaklar
- Aşırı generic'leşme: İki yerden çağrılan bir fonksiyona 4 generic parametre eklemek okunabilirliği bitirir. Önce somut tipi yazın, ihtiyaç çıkınca soyutlayın.
- Constraint'siz T:
<T>deyip içindet.name'e erişemezsiniz;extends { name: string }şarttır. - Conditional type'ın okunabilirliği: Üst üste iç içe koşullar, başkası bir yana, üç ay sonra siz de okuyamazsınız. Karmaşık koşulları ara
typetanımlarına bölün. - any yerine unknown: Gerçekten tipi bilinmeyen bir değer için
anydeğilunknownkullanın;unknownüzerinde işlem yapmadan önce daraltma zorunludur.

İleri tip sistemini öğrenmenin zor tarafı sözdizimi değil, ne zaman hangi aracı kullanacağınızı sezmek. any yazma isteği geldiğinde durup "burada aslında ne bilmiyorum?" diye sorun: cevap "çağıran söyleyecek" ise generic, "gelen tipe göre değişecek" ise conditional type istiyorsunuz demektir. Birkaç hafta bu refleksle yazılmış kod, hem siz hem de sizi takip edenler için çok daha az hata ayıklama anlamına gelir. Detaylı pratik örnekler ve egzersizler için ilgili eğitim içeriğini inceleyebilirsiniz.



