TypeScript Utility Types: Partial, Pick, Omit ve Daha Fazlası

TypeScript Utility Types: Partial, Pick, Omit ve Daha Fazlası
TypeScript, mevcut tiplerden yeni tipler türetmenizi sağlayan güçlü yerleşik utility type'lar sunar. Bu araçlar, kod tekrarını azaltır ve tip sisteminin gücünden tam olarak yararlanmanızı sağlar. Bu yazıda en çok kullanılan utility type'ları detaylı örneklerle inceleyeceğiz.
Partial<T>
Bir tipin tüm özelliklerini opsiyonel yapar. Güncelleme işlemlerinde çok kullanılır:
interface Kullanici {
id: number;
isim: string;
email: string;
yas: number;
adres: string;
}
// Tüm alanlar opsiyonel olur
type KullaniciGuncelleme = Partial<Kullanici>;
function kullaniciGuncelle(id: number, guncellemeler: Partial<Kullanici>): void {
// Sadece gönderilen alanlar güncellenir
console.log(`Kullanıcı ${id} güncelleniyor:`, guncellemeler);
}
kullaniciGuncelle(1, { isim: "Tarik Tunç" });
kullaniciGuncelle(1, { email: "yeni@email.com", yas: 29 });
Required<T>
Partial'ın tersi: tüm opsiyonel özellikleri zorunlu yapar:
interface Ayarlar {
tema?: "light" | "dark";
dil?: string;
bildirimler?: boolean;
fontSize?: number;
}
// Tüm alanlar zorunlu
type ZorunluAyarlar = Required<Ayarlar>;
const varsayilanAyarlar: ZorunluAyarlar = {
tema: "light",
dil: "tr",
bildirimler: true,
fontSize: 16
};
Pick<T, K> ve Omit<T, K>
interface Urun {
id: number;
ad: string;
fiyat: number;
aciklama: string;
stok: number;
kategori: string;
resimUrl: string;
}
// Sadece belirli alanları seç
type UrunKart = Pick<Urun, "id" | "ad" | "fiyat" | "resimUrl">;
// Belirli alanları çıkar
type UrunOlustur = Omit<Urun, "id">;
// Kombine kullanım
type UrunGuncelle = Partial<Omit<Urun, "id">> & { id: number };
function urunListele(): UrunKart[] {
// Sadece kart için gerekli verileri döndür
return [
{ id: 1, ad: "Laptop", fiyat: 25000, resimUrl: "/img/laptop.jpg" }
];
}
function urunOlustur(urun: UrunOlustur): Urun {
return { ...urun, id: Date.now() };
}
Partial<Omit<T, "id">> & Pick<T, "id"> kalıbı, id zorunlu diğer alanlar opsiyonel olan bir güncelleme tipi oluşturur.
Record<K, T>
Anahtar-değer çiftlerinden oluşan bir nesne tipi oluşturur:
// String anahtarlı record
type SayfaDurumlari = Record<string, boolean>;
const sayfalar: SayfaDurumlari = {
anasayfa: true,
hakkinda: false,
iletisim: true
};
// Union anahtar ile record
type HttpDurum = 200 | 301 | 404 | 500;
type DurumMesajlari = Record<HttpDurum, string>;
const mesajlar: DurumMesajlari = {
200: "Başarılı",
301: "Yönlendirme",
404: "Bulunamadı",
500: "Sunucu Hatası"
};
// Enum ile record
enum Rol {
Admin = "admin",
Editor = "editor",
Okuyucu = "okuyucu"
}
type RolYetkileri = Record<Rol, string[]>;
const yetkiler: RolYetkileri = {
[Rol.Admin]: ["okuma", "yazma", "silme", "yonetim"],
[Rol.Editor]: ["okuma", "yazma"],
[Rol.Okuyucu]: ["okuma"]
};
Exclude<T, U> ve Extract<T, U>
type Primitifler = string | number | boolean | null | undefined;
// null ve undefined'ı çıkar
type GecerliPrimitifler = Exclude<Primitifler, null | undefined>;
// string | number | boolean
// Sadece string ve number'ı çıkar
type MetinVeSayi = Extract<Primitifler, string | number>;
// string | number
// Pratik kullanım: Event tipleri
type MouseOlaylari = "click" | "dblclick" | "mousedown" | "mouseup" | "mousemove";
type KlavyeOlaylari = "keydown" | "keyup" | "keypress";
type TumOlaylar = MouseOlaylari | KlavyeOlaylari;
type SadeceMouseOlaylari = Extract<TumOlaylar, MouseOlaylari>;
ReturnType<T> ve Parameters<T>
function kullaniciOlustur(isim: string, yas: number, email: string) {
return {
id: Math.random(),
isim,
yas,
email,
kayitTarihi: new Date()
};
}
// Fonksiyon dönüş tipini al
type Kullanici = ReturnType<typeof kullaniciOlustur>;
// { id: number; isim: string; yas: number; email: string; kayitTarihi: Date }
// Fonksiyon parametre tiplerini al
type KullaniciParams = Parameters<typeof kullaniciOlustur>;
// [string, number, string]
// Async fonksiyon için
async function veriGetir(): Promise<{ id: number; data: string[] }> {
return { id: 1, data: ["a", "b"] };
}
type VeriTipi = Awaited<ReturnType<typeof veriGetir>>;
// { id: number; data: string[] }
NonNullable<T> ve Readonly<T>
// NonNullable - null ve undefined'ı kaldır
type BelkiString = string | null | undefined;
type KesınString = NonNullable<BelkiString>; // string
// Readonly - tüm özellikleri salt okunur yap
interface Ayarlar {
tema: string;
dil: string;
bildirimler: boolean;
}
const sabitAyarlar: Readonly<Ayarlar> = {
tema: "dark",
dil: "tr",
bildirimler: true
};
// sabitAyarlar.tema = "light"; // HATA! readonly özellik değiştirilemez
// Deep Readonly (yerleşik değil, özel implementasyon)
type DeepReadonly<T> = {
readonly [K in keyof T]: T[K] extends object ? DeepReadonly<T[K]> : T[K];
};
Readonly<T> sadece birinci seviye özellikleri korur. İç içe nesneler hâlâ değiştirilebilir. Derin readonly için özel bir utility type oluşturmanız veya as const assertion kullanmanız gerekir.
Utility Type'ları Birleştirme
// Gerçek dünya senaryosu: Form yönetimi
interface FormVerisi {
isim: string;
email: string;
sifre: string;
telefon: string;
adres: string;
sehir: string;
}
// Kayıt formu - tüm alanlar zorunlu
type KayitFormu = Required<FormVerisi>;
// Profil güncelleme - id zorunlu, geri kalanı opsiyonel
type ProfilGuncelleme = Pick<FormVerisi, "isim" | "email"> &
Partial<Omit<FormVerisi, "isim" | "email" | "sifre">>;
// Şifre hariç readonly profil
type ProfilGoruntule = Readonly<Omit<FormVerisi, "sifre">>;
// Doğrulama hataları
type FormHatalari = Partial<Record<keyof FormVerisi, string>>;
Partial<Omit<T, "id">> kalıbıdır; bu, güncelleme işlemlerinde id hariç tüm alanları opsiyonel yapar.
Sonuç
TypeScript utility type'ları, mevcut tiplerden yeni tipler türetmenin en verimli yoludur. Partial, Pick, Omit, Record ve diğer utility type'ları ustalıkla kullanmak, tip tekrarını azaltır ve kodunuzun bakımını kolaylaştırır. Bu type'ları kombinleyerek karmaşık iş mantığını tip seviyesinde ifade edebilirsiniz.