TypeScript utility types, var olan bir tipten yeni bir tip türetmenizi sağlayan ve her projede global olarak hazır bulunan generic tiplerdir. Örneğin Partial<Kullanici> tüm alanları isteğe bağlı yapar, Omit<Kullanici, "sifre"> bir alanı çıkarır, ReturnType<typeof f> bir fonksiyonun dönüş tipini verir. Hiçbirini içe aktarmanız (import) gerekmez.

Bu yazıda resmî Utility Types sayfasında listelenen tiplerin tamamını bir tabloda topluyor, en çok kullanılanları TypeScript 6.0 ile denenmiş örneklerle açıklıyoruz. Bu tiplerin arkasındaki mekanizmayı merak ediyorsanız mapped types ve conditional types yazılarımıza bakabilirsiniz; TypeScript ileri seviye özeti ise konuya kısa bir giriş sunuyor.

Tüm utility types tek tabloda

Tüm utility types tek tabloda: Awaited, Partial, Required, Readonly

Aşağıdaki tablo resmî belgedeki sırayı ve her tipin ilk geldiği TypeScript sürümünü gösterir. Dört string tipi (Uppercase ve diğerleri) derleyiciye gömülü "intrinsic" tiplerdir ve template literal types yazımızda ayrıca anlatılır.

TipNe yaparSürüm
Awaited<T>Promise içini await gibi özyinelemeli açar4.5
Partial<T>Tüm özellikleri isteğe bağlı (?) yapar2.1
Required<T>Tüm özellikleri zorunlu yapar, ? işaretini kaldırır2.8
Readonly<T>Tüm özellikleri readonly yapar2.1
Record<K, T>Anahtarları K, değerleri T olan nesne tipi kurar2.1
Pick<T, K>T içinden yalnızca K anahtarlarını seçer2.1
Omit<T, K>T içinden K anahtarlarını çıkarır3.5
Exclude<U, E>Union üyelerinden E'ye atanabilenleri atar2.8
Extract<T, U>Union üyelerinden U'ya atanabilenleri tutar2.8
NonNullable<T>null ve undefined'ı çıkarır2.8
Parameters<F>Fonksiyon parametrelerini tuple olarak verir3.1
ConstructorParameters<C>Yapıcı parametrelerini tuple olarak verir3.1
ReturnType<F>Fonksiyonun dönüş tipini verir2.8
InstanceType<C>Yapıcının ürettiği örnek tipini verir2.8
NoInfer<T>T'yi değiştirmez, yalnızca çıkarımı engeller5.4
ThisParameterType<F>Fonksiyonun this parametresinin tipini verir3.3
OmitThisParameter<F>this parametresini imzadan çıkarır3.3
ThisType<T>Nesne literalinde this için bağlamsal tip işaretler2.3
Uppercase, Lowercase, Capitalize, UncapitalizeString literal tiplerinde harf dönüşümü4.1

Partial, Required ve Readonly

Partial<T>, bir tipin olası tüm alt kümelerini temsil eder. En tipik kullanım alanı güncelleme fonksiyonlarıdır: kullanıcı yalnızca değiştirmek istediği alanları gönderir.

typescript
interface Ayar {
  tema: "acik" | "koyu";
  dil: string;
  bildirim: boolean;
}

function guncelle(ayar: Ayar, degisen: Partial<Ayar>): Ayar {
  return { ...ayar, ...degisen };
}

const ilk: Ayar = { tema: "acik", dil: "tr", bildirim: true };
const yeni = guncelle(ilk, { tema: "koyu" });
console.log(yeni); // { tema: 'koyu', dil: 'tr', bildirim: true }

Required<T> bunun tersidir: isteğe bağlı alanları zorunlu hale getirir. TypeScript 2.8 sürüm notlarına göre strictNullChecks açıkken ? kaldırılırken o özelliğin tipinden undefined de çıkarılır. TypeScript 6.0 ile strict varsayılan olarak açık geldiği için bu davranış yeni projelerde varsayılandır.

typescript
interface Secenek {
  port?: number;
  host?: string;
}

const s1: Secenek = { port: 8080 };

const s2: Required<Secenek> = { port: 8080 };
// TS2741: Property 'host' is missing in type '{ port: number; }' but required in type 'Required<Secenek>'.

Readonly<T> tüm özellikleri yeniden atanamaz yapar. Dikkat: bu yalnızca derleme zamanı korumasıdır, üretilen JavaScript'te nesne dondurulmaz. Gerçek dondurma için Object.freeze kullanırsınız; onun TypeScript tanımı da zaten Readonly<T> döndürür.

typescript
interface Gorev {
  baslik: string;
}

const g: Readonly<Gorev> = { baslik: "Yedek al" };

g.baslik = "Sil";
// TS2540: Cannot assign to 'baslik' because it is a read-only property.

Record: anahtar kümesinden nesne tipi

Record: anahtar kümesinden nesne tipi

Record<K, T>, anahtarları K olan ve her değeri T tipinde olan bir nesne tipi kurar. K bir string literal union ise her anahtar zorunlu olur; böylece bir dil ya da durum eklendiğinde unutulan yerleri derleyici gösterir:

typescript
type Dil = "tr" | "en";

const selam: Record<Dil, string> = {
  tr: "Merhaba",
};
// TS2741: Property 'en' is missing in type '{ tr: string; }' but required in type 'Record<Dil, string>'.

const sayac: Record<string, number> = {};
sayac["ziyaret"] = 1;

Record<string, number> ise index signature ile aynı anlama gelir. İkisinin farkını index signature ve Record yazımızda karşılaştırıyoruz.

Pick ve Omit

Pick istediğiniz alanları seçer, Omit istemediklerinizi atar. Örneğin bir kullanıcı tipinden herkese açık bir görünüm ve şifresiz bir kayıt tipi türetmek:

typescript
interface Kullanici {
  id: number;
  ad: string;
  eposta: string;
  sifre: string;
}

type Profil = Pick<Kullanici, "id" | "ad">;
// { id: number; ad: string; }

type GuvenliKullanici = Omit<Kullanici, "sifre">;
// { id: number; ad: string; eposta: string; }

const p: Profil = { id: 1, ad: "Can" };

İkisi arasında önemli bir fark var: Pick'in ikinci parametresi keyof T ile kısıtlıdır, Omit'inki değildir. Bu yüzden Omit'e yanlış yazılmış bir anahtar verirseniz hiçbir uyarı almazsınız:

typescript
interface Kullanici {
  id: number;
  sifre: string;
}

type A = Omit<Kullanici, "sifr">;
// Hata yok: { id: number; sifre: string; } (hiçbir şey çıkarılmadı)

type B = Pick<Kullanici, "sifr">;
// TS2344: Type '"sifr"' does not satisfy the constraint 'keyof Kullanici'.

Union süzme: Exclude, Extract, NonNullable

Bu üç tip union'lar üzerinde çalışır. Exclude belirli üyeleri atar, Extract yalnızca eşleşenleri tutar, NonNullable ise null ve undefined'ı temizler. Discriminated union'larda belirli bir varyantı ayıklamak için çok kullanışlıdırlar:

typescript
type Sekil =
  | { tur: "daire"; yaricap: number }
  | { tur: "kare"; kenar: number }
  | { tur: "ucgen"; taban: number; yukseklik: number };

type DaireDisi = Exclude<Sekil, { tur: "daire" }>;
// { tur: "kare"; kenar: number; } | { tur: "ucgen"; taban: number; yukseklik: number; }

type Daire = Extract<Sekil, { tur: "daire" }>;
// { tur: "daire"; yaricap: number; }

type T0 = Exclude<"a" | "b" | "c", "a">;           // "b" | "c"
type T1 = NonNullable<string[] | null | undefined>; // string[]

Bu tipler aslında conditional type olarak tanımlıdır; union üzerinde dağılarak (distributive) her üyeyi tek tek değerlendirirler. Bu mekanizmayı conditional types yazımızda adım adım gösteriyoruz.

Fonksiyon ve sınıf tiplerinden tip çıkarmak

ReturnType, Parameters ve Awaited birlikte kullanıldığında bir fonksiyonun tipini elle tekrar yazmanıza gerek kalmaz. Bunlar tip bekler; elinizdeki bir fonksiyon değeri olduğu için typeof ile tipini almanız gerekir:

typescript
async function siparisGetir(id: number, detayli: boolean) {
  return { id, toplam: 250, detayli };
}

type Arg = Parameters<typeof siparisGetir>;
// [id: number, detayli: boolean]

type Donus = ReturnType<typeof siparisGetir>;
// Promise<{ id: number; toplam: number; detayli: boolean; }>

type Siparis = Awaited<Donus>;
// { id: number; toplam: number; detayli: boolean; }

type IcIce = Awaited<Promise<Promise<number>>>; // number

İki ayrıntıya dikkat edin. Birincisi, aşırı yüklenmiş (overload) fonksiyonlarda ReturnType ve Parameters son imzayı esas alır. İkincisi, fonksiyon olmayan bir tip verirseniz derleyici kısıt hatası verir. Sınıflar için aynı işi ConstructorParameters ve InstanceType yapar:

typescript
class Baglanti {
  constructor(public host: string, public port: number) {}
}

type YapiciArg = ConstructorParameters<typeof Baglanti>;
// [host: string, port: number]

type Ornek = InstanceType<typeof Baglanti>; // Baglanti

type Hatali = ReturnType<string>;
// TS2344: Type 'string' does not satisfy the constraint '(...args: any) => any'.

NoInfer: çıkarımı tek kaynaktan yapmak

TypeScript 5.4 ile gelen NoInfer<T>, içindeki tipi değiştirmez; yalnızca derleyiciye "bu konumdan tip çıkarma" der. Sürüm notlarındaki örneğe benzer bir senaryo: renk listesi tek doğru kaynak olmalı, varsayılan renk de bu listeden biri olmalı.

typescript
function lambaKur<C extends string>(renkler: C[], varsayilan?: NoInfer<C>) {
  return { renkler, varsayilan };
}

lambaKur(["kirmizi", "sari", "yesil"], "kirmizi"); // geçerli

lambaKur(["kirmizi", "sari", "yesil"], "mavi");
// TS2345: Argument of type '"mavi"' is not assignable to parameter of type '"kirmizi" | "sari" | "yesil" | undefined'.

NoInfer olmadan derleyici "mavi" değerini de bir aday sayar ve C'yi dört renkli bir union olarak çıkarır; çağrı hatasız geçer. Generic çıkarımın genel mantığı için generics yazımıza bakabilirsiniz.

this ile ilgili üç tip

ThisParameterType<F>, bir fonksiyonun açıkça yazılmış this parametresinin tipini verir; yoksa unknown döner. OmitThisParameter<F> bu parametreyi imzadan çıkarır; bind ile bağlanmış bir fonksiyonu tiplemek için kullanılır. ThisType<T> ise yeni bir tip üretmez, nesne literalindeki metotlarda this'in tipini işaretleyen bir belirteçtir ve noImplicitThis açık olmalıdır. noImplicitThis strict ailesinin parçasıdır; strict modu açıksa ayrıca bir şey yapmanız gerekmez.

typescript
function onaltilik(this: Number) {
  return this.toString(16);
}

type Bu = ThisParameterType<typeof onaltilik>; // Number

const yirmiAlti: OmitThisParameter<typeof onaltilik> = onaltilik.bind(26);
console.log(yirmiAlti()); // 1a

Utility types'ı birleştirmek

Utility types iç içe kullanılabilir. Örneğin "id zorunlu, diğer alanlar isteğe bağlı" bir güncelleme tipi:

typescript
interface Urun {
  id: number;
  ad: string;
  fiyat: number;
}

type UrunGuncelle = Pick<Urun, "id"> & Partial<Omit<Urun, "id">>;

const u1: UrunGuncelle = { id: 7, fiyat: 99 };

const u2: UrunGuncelle = { fiyat: 99 };
// TS2322: Type '{ fiyat: number; }' is not assignable to type 'UrunGuncelle'.
//   Property 'id' is missing in type '{ fiyat: number; }' but required in type 'Pick<Urun, "id">'.

Sık yapılan hatalar

Sık yapılan hatalar: Readonly'yi çalışma zamanı koruması sanmak, Omit'te yazım hatası, Değeri tip yerine vermek, Overload'larda tüm imzaları beklemek
  • Readonly'yi çalışma zamanı koruması sanmak: Readonly yalnızca derleyiciyi durdurur; JavaScript tarafında nesne değiştirilebilir kalır.
  • Omit'te yazım hatası: Omit anahtarları keyof T ile denetlemez; yanlış anahtar sessizce yok sayılır. Kritik yerlerde Pick ile tersten tanımlamak daha güvenlidir.
  • Değeri tip yerine vermek: ReturnType<siparisGetir> yazmak TS2749 hatası verir; doğrusu ReturnType<typeof siparisGetir>. Ayrıntılar typeof tip operatörü yazımızda.
  • Overload'larda tüm imzaları beklemek: ReturnType ve Parameters yalnızca son imzaya bakar.
  • Partial'ın derin olduğunu sanmak: iç içe nesneler etkilenmez.

Sık Sorulan Sorular

Utility types'ı import etmem gerekir mi?

Hayır. Bu tipler TypeScript'in standart kütüphane tanımlarında (lib dosyaları) global olarak bildirilir; Uppercase gibi intrinsic olanlar ise doğrudan derleyicinin içindedir.

Pick mi Omit mi kullanmalıyım?

Seçeceğiniz alanlar azsa Pick, çıkaracağınız alanlar azsa Omit daha kısa olur. Anahtar denetimi önemliyse Pick daha güvenlidir, çünkü olmayan bir anahtarı kabul etmez.

Awaited ile ReturnType arasındaki fark nedir?

ReturnType async bir fonksiyon için Promise<...> döndürür. Promise'in içindeki değeri almak için sonucu Awaited ile sarmanız gerekir. Awaited iç içe Promise'leri de özyinelemeli açar. Promise'in çalışma mantığı için JavaScript Promise yazımıza bakabilirsiniz.

Kendi utility tipimi yazabilir miyim?

Evet. Yerleşik tiplerin çoğu mapped types ve conditional types ile yazılmıştır; aynı araçlarla kendi tiplerinizi kurabilirsiniz.

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 · TypeScript generics · Mapped types · keyof ve typeof · Index signature ve Record · TypeScript ileri seviye özeti