JavaScript geliştiricileri TypeScript'e geçtiğinde genellikle temel ilkel türlerle, arayüzlerle ve birleşik türlerle başlar. Bu türler birçok günlük senaryoyu kapsasa da, büyük ölçekli ve sürdürülebilir uygulamalar geliştirmek, tür sisteminin daha derin bir anlayışını gerektirir. TypeScript'teki gelişmiş türler, esnek, yeniden kullanılabilir ve sıkı denetime tabi kod yapıları oluşturmak için gerekli araçları sağlar. Bu yazıda en kritik gelişmiş tür özellikleri olan Jenerikler, Yardımcı Türler ve Eşlenen Türler ele alınmaktadır.
Jenerikler: Yeniden Kullanılabilir ve Tür Güvenli Kod Yazma
Jenerikler, tek bir tür yerine çeşitli türlerle çalışan bileşenler oluşturmanıza olanak tanır. Tür bilgisini any kullanmaya başvurmadan kod tabanınız boyunca korumayı sağlayarak türler için "yer tutucular" tanımlamanıza izin verirler.
Basit bir API yanıt işleyicisini düşünün. Jenerikler olmadan, genel bir nesne döndürüyor veya derleme zamanı güvenliğini kaybeden dinamik türlemeye güveniyor olabilirsiniz. Jenerikler kullanarak, yanıt gövdesinin beklenen arayüzle eşleştiğinden emin olabilirsiniz.
interface ApiResponse<T> {
data: T;
status: number;
message: string;
}
function handleResponse<T>(response: Response): Promise<ApiResponse<T>> {
return response.json().then((data) => ({
data,
status: response.status,
message: 'Success'
}));
}
// Kullanım: TypeScript artık 'user'ın şeklini biliyor
const user = await handleResponse<{ id: number; name: string }>(response);
console.log(user.data.name);
Bu örnekte, jenerik tür T, ApiResponse arayüzünün esnek olmasını sağlar. handleResponse çağrıldığında, TypeScript verinin belirli yapısını çıkarır ve user.data.name için otomatik tamamlama ve tür denetimi sağlar.
Yardımcı Türler: Tür Sisteminden Yararlanma
TypeScript, yaygın tür dönüşümleri gerçekleştiren yerleşik yardımcı türler kümesi içerir. Bunları kullanmak, tekrar eden kodu (boilerplate) önemli ölçüde azaltabilir ve sürdürülebilirliği artırabilir.
1. Partial ve Required
Partial<T> yardımcı türü, T'nin tüm özelliklerini isteğe bağlı olarak ayarlanmış bir tür oluşturur. Bu, yalnızca değiştirmek istediğiniz alanları göndermenin yeterli olduğu REST API'lerindeki güncelleme işlemleri için özellikle kullanışlıdır.
interface User {
id: string;
email: string;
name: string;
}
// Yalnızca email ve name isteğe bağlıdır
type UpdateUserDto = Partial<User>;
const update: UpdateUserDto = { email: 'new@example.com' };
Bunun tersine, Required<T> tüm özellikleri zorunlu hale getirir; bu, karmaşık koşullu mantık nedeniyle kısmen türlenmiş olabilecek nesnelerle uğraşırken yararlı olabilir.
2. Pick ve Omit
Bir arayüzün bir alt kümesine ihtiyacınız olduğunda, Pick<T, K> belirli anahtarları seçmenize olanak tanır. Benzer şekilde, Omit<T, K> belirtilen anahtarları hariç tutarak bir tür oluşturur.
// Hassas şifre verisini hariç tutan bir tür oluşturun
type PublicUser = Omit<User, 'password' | 'ssn'>;
Eşlenen Türler: Dinamik Tür Oluşturma
Eşlenen türler, mevcut bir türün anahtarları üzerinde yineleme yaparak yeni türler oluşturmanıza olanak tanır. Bu, tüm özellikleri salt okunur veya null yapılması gibi mevcut yapıların varyasyonlarını oluşturmak için güçlüdür.
// T'nin tüm özelliklerini salt okunur yapar
type Readonly<T> = {
readonly [P in keyof T]: T[P];
};
// T'nin tüm özelliklerini isteğe bağlı yapar
type Nullable<T> = {
[P in keyof T]: T[P] | null;
};
interface Config {
host: string;
port: number;
}
const readOnlyConfig: Readonly<Config> = { host: 'localhost', port: 3000 };
readOnlyConfig.host = 'remote'; // Hata: 'host' salt okunur bir özellik olduğu için atanamaz.
Bu özellik, genellikle TypeScript'in standart kütüphanesi içinde dahili olarak kullanılır ve giriş yapılarına dinamik olarak adapte olan gelişmiş tür yardımcı programları oluşturmak için gereklidir.
Koşullu Türler ve Şablit Harf Türleri
Biraz daha karmaşık olsalar da, Koşullu Türler tür sistemi içinde tür kontrolleri yapmanıza olanak tanır. Üçlü operatör sözdizimini takip ederler: T extends U ? X : Y.
type IsString<T> = T extends string ? "It's a string" : "Not a string";
type Result1 = IsString<"hello">; // "It's a string"
type Result2 = IsString<123>; // "Not a string"
TypeScript 4.1'de tanıtılan Şablit Harf Türleri, dize sabiti manipülasyonunu etkinleştirerek gelişmiş tür güvenli olay işleme ve rota tanımlamalarına olanak tanır.
Sonuç
Gelişmiş TypeScript türlerini ustalaşmak, sadece zeki kod yazmakla ilgili değildir; geliştirici deneyimini artırmak ve çalışma zamanı hatalarını azaltmakla ilgilidir. Jenerikler, Yardımcı Türler, Eşlenen Türler ve Koşullu Türlerden yararlanarak, yalnızca tür güvenli değil, aynı zamanda son derece ifade edici ve sürdürülebilir uygulamalar oluşturabilirsiniz. TypeScript ile çalışmaya devam ettikçe, basit birleşik türleri daha sağlam jenerik yapılara yeniden düzenlemek için kendinizi zorlayın. Başlangıçtaki öğrenme eğrisi, uzun vadede inanılmaz derecede ödül verir; bu da kod tabanlarının anlaşılmasını, hata ayıklamasını ve ölçeklenmesini kolaylaştırır.