Daha Az Kod, Daha Çok Tip: Utility Types Rehberi
Kod tekrarı (yani DRY kuralını ihlal etmek), her geliştiricinin kâbusudur. Kopyala-yapıştır cenneti gibi görünür ama zamanla refactor cehennemine dönüşür. 😊 Neyse ki TypeScript bu konuda yalnız değilsin diyor ve elimize bir avuç sihirli araç veriyor: Utility Types!
Bu küçük ama etkili tip yardımcıları, tipleri yeniden tanımlamak yerine onları dönüştürmene, sadeleştirmene ve yeniden kullanmana olanak tanır. Hem kodu temizler, hem de tip güvenliğini artırır. Kısacası: daha az kod, daha fazla akıl sağlığı.
Partial
Bir tipin tüm alanlarını opsiyonel hale getirir. Özellikleupdate, patch veya form işleme fonksiyonlarında harika işler çıkarır.type User = { id: number; name: string; age: number };
const updateUser = (user: Partial<User>) => {
// sadece değişen alanlar gönderilebilir
};
Artık updateUser({ name: 'Cansu' }) gayet geçerli. Çünkü Partial sayesinde User tipinin tüm alanları artık isteğe bağlı.
Bonus: Partial’ı derin yapılarda kullanmak istersen, DeepPartial adında custom versiyonlar da yaratabilirsin.
Pick
Bir tipten sadece belirli alanları seçmek istediğinde Pick imdadına yetişir.type User = { id: number; name: string; age: number; email: string };
type UserPreview = Pick<User, 'id' | 'name'>;
Artık UserPreview sadece id ve name alanlarını içerir. Listeleme sayfalarında ya da basit kart bileşenlerinde tam da ihtiyacın olan şeydir.
Omit
Pick’in kardeşi ama biraz huysuz olanı. ☺️ Belirli alanları hariç tutar.type UserWithoutAge = Omit<User, 'age'>;
Yani UserWithoutAge, User tipinden age alanını çıkarır. Özellikle hassas veya gereksiz alanları arayüzden soyutlamak için kullanılır.
Record
Bir anahtar-değer eşleşmesi oluşturmak istediğinde Record mükemmel bir çözümdür. Sözlük gibi çalışır.type Roles = 'admin' | 'user';
const permissions: Record<Roles, boolean> = {
admin: true,
user: false,
};
Artık permissions.admin ya da permissions.user dediğinde otomatik olarak tip kontrolü alırsın. Yanlış role yazarsan TypeScript anında kızar (ama sevgiyle 💙).
Readonly ve Required
Readonly<T> → Objeleri değiştirilemez hale getirir. Required<T> → Opsiyonel alanları zorunlu hale getirir.Bu ikili, özellikle API response’larını ya da config objelerini koruma altına almak için birebirdir.
type Config = { apiKey?: string; version?: number };
type StrictConfig = Required<Readonly<Config>>;
Artık bu yapıdaki alanları ne eksik gönderebilir ne de değiştirebilirsin. Güvenli, sert, tam bir TypeScript bodyguard’ı.
ReturnType ve Parameters
Bir fonksiyonun dönüş veya parametre tipini tekrar yazmak yerine otomatik çıkarabiliriz.function createUser(name: string, age: number) {
return { name, age, active: true };
}
type UserReturn = ReturnType<typeof createUser>; // { name: string; age: number; active: boolean }
Aynı şekilde Parameters<typeof createUser> sana [string, number] şeklinde bir tuple döner. Böylece fonksiyon imzalarıyla oynarken tip uyumsuzlukları tarihe karışır.
Exclude ve Extract
Bu iki kardeş tam bir zıt kutup ikilisi:Exclude<T, U>→ T tipinden U’yu hariç tutar.Extract<T, U>→ Sadece U’ya uyan kısımları seçer.
type Status = 'pending' | 'success' | 'error';
type NonError = Exclude<Status, 'error'>; // 'pending' | 'success'
Böylece union tipleri üzerinde ince ayar yapabilirsin.
Neden Kullanılır?
- Kod tekrarını ciddi şekilde azaltır.
- Tip güvenliğini artırır.
- Refactor sırasında hata riskini düşürür.
- Karmaşık tipleri sadeleştirir.
- Büyük ekiplerde ortak tiplerin sürdürülebilirliğini sağlar.
- Ve en önemlisi: “Bu tip zaten vardı, neden bir daha yazdık?” krizlerini önler. 🙃
Gerçek Hayat Örneği
Bir API response tipini düşünelim:type ApiResponse<T> = {
data: T;
status: number;
error?: string;
};
Bunu kullanarak yüzlerce endpoint’i tek bir yapı üzerinden tipleyebilirsin. ApiResponse<User> ya da ApiResponse<Product> gibi türevler sayesinde backend ve frontend arasında tam bir tip senkronu sağlanır. Utility Types bu tür esnek, modüler sistemler için altın değerindedir.
Sonuç
Utility Types, TypeScript’in gizli kahramanlarıdır. Daha az kod, daha fazla düzen, daha az hata, daha fazla huzur. Kodun okunabilirliği artar, refactor korkusu azalır ve proje ölçeklense bile tip sistemi seninle birlikte büyür.Utility Types kullanmak sadece akıllıca değil, aynı zamanda tembeller için zekice bir harekettir. 😊