---
title: 'Koşullu Tipler'
source: 'https://academia.sh/tr/kurslar/typescript/kosullu-tipler'
course: TypeScript
language: tr
updated: '2026-08-17T18:09:53+00:00'
license: 'CC BY-SA 4.0'
---

# Koşullu Tipler

Tip düzeyinde dallanma, birleşimler üzerinde dağılım kuralı ve dağılımın kapatılması, infer ile tip parçası çıkarma ve koşullu dönüş tiplerinin sınırı.

Önceki derste `T[A] extends number ? A : never` biçiminde bir yazım geçti ve tip düzeyinde
bir dallanma yaptı. **Koşullu tip** (conditional type), tip sisteminin hesaplama
yeteneğinin merkezindeki yapıdır: bir tipin başka bir tipe atanabilir olup olmadığına göre
iki tipten birini seçer.

Yazımı üçlü işlecin tip düzeyindeki karşılığıdır:

$$
T \text{ extends } U \;?\; X : Y
$$

Bu ders koşulun nasıl değerlendirildiğini, birleşimler üzerindeki özel davranışını,
`infer` ile parça çıkarmayı ve yapının sınırlarını ele alır.

## Tip Düzeyinde Dallanma

```typescript
type SayiMi<T> = T extends number ? "sayi" : "sayi degil";

const a: SayiMi<number> = "sayi";
const b: SayiMi<string> = "sayi degil";
console.log(a, b);

const c: SayiMi<number> = "sayi degil";
```

```text
p1.ts(7,7): error TS2322: Type '"sayi degil"' is not assignable to type '"sayi"'.
```

`SayiMi<number>` tipi `"sayi"`, `SayiMi<string>` tipi `"sayi degil"` olarak çözülür.
Yedinci satırın tanısı, çözümün gerçekten yapıldığını gösterir: derleyici `SayiMi<number>`
yerine `"sayi"` yazarak hatayı bildirir.

`extends` sözcüğü buradaki anlamıyla kalıtım değil **atanabilirlik** sınamasıdır: "`T`,
`U`'nun beklendiği yere konabilir mi?" Yapısal tipleme dersinde kurulan kurallar burada
uygulanır.

## Dağılım

Koşullu tipin tip parametresi bir birleşimse, koşul her üye için **ayrı ayrı**
değerlendirilir ve sonuçların birleşimi alınır. Buna **dağılım** (distribution) denir:

```typescript
type SayiMi<T> = T extends number ? "sayi" : "sayi degil";
type Dagilmayan<T> = [T] extends [number] ? "sayi" : "sayi degil";

declare const dagilan: SayiMi<number | string>;
declare const kapali: Dagilmayan<number | string>;

const x: null = dagilan;
const y: null = kapali;
```

```text
p2.ts(7,7): error TS2322: Type '"sayi degil" | "sayi"' is not assignable to type 'null'.
  Type '"sayi degil"' is not assignable to type 'null'.
p2.ts(8,7): error TS2322: Type '"sayi degil"' is not assignable to type 'null'.
```

Tanılar iki tipi de açıkça yazıyor. `SayiMi<number | string>` tipi
`"sayi degil" | "sayi"` olmuş; koşul önce `number`, sonra `string` için
değerlendirilmiştir. `Dagilmayan<number | string>` ise tek bir sonuç vermiştir:
`"sayi degil"`.

Dağılımı kapatan şey, tip parametresinin **demet içine alınmasıdır**. `[T] extends [U]`
yazımında sınanan artık `T` değil, tek elemanlı bir demettir; birleşim üyelerine ayrılmaz
ve koşul bir kez değerlendirilir.

İki davranıştan hangisinin isteneceği amaca bağlıdır. Bir birleşimin her üyesini
dönüştürmek isteniyorsa dağılım gerekir. "Bu tipin **tümü** şu koşulu sağlıyor mu?"
sorusuna yanıt aranıyorsa kapatılmalıdır — aksi hâlde `number | string` birleşimi için
"kısmen sayı" gibi anlamsız bir sonuç çıkar.

Dağılım yalnızca **çıplak** tip parametrelerinde geçerlidir: koşulun sol tarafı doğrudan
`T` olmalıdır. `T[]`, `[T]` ya da `{ deger: T }` yazımlarında dağılım olmaz.

## Süzme: `Cikar`

Dağılımın en yaygın kullanımı, bir birleşimden üye elemektir. Elenecek üye için `never`
üretilir; `never` bir birleşimde yer kaplamaz:

```typescript
type Cikar<T, U> = T extends U ? never : T;

type Birim = "C" | "Pa" | "%";
type OlculebilirBirim = Cikar<Birim, "%">;

const birimler: OlculebilirBirim[] = ["C", "Pa"];
console.log(birimler.join(","));
```

Çıktı `C,Pa`dır. Dosyanın sonuna, bir boş satırdan sonra
`const yanlis: OlculebilirBirim = "%";` satırı eklenirse:

```text
p5.ts(9,7): error TS2322: Type '"%"' is not assignable to type 'OlculebilirBirim'.
```

Hesabın adımları şöyledir: koşul üç üye için ayrı ayrı değerlendirilir; `"C"` ve `"Pa"`
için `"%"` tipine atanamadıklarından kendileri, `"%"` için ise `never` üretilir. Sonuç
`"C" | "Pa" | never` yani `"C" | "Pa"`dır.

Bu dönüşümün standart kitaplıktaki karşılığı `Exclude`tur ve Yardımcı Tipler dersinde ele
alınacaktır.

## `infer` ile Parça Çıkarma

Koşulun sol tarafında `infer` sözcüğüyle bir tip değişkeni bildirilebilir. Derleyici,
eşleştirme sırasında o değişkene karşılık gelen tipi bulur:

```typescript
interface Olcum {
  kimlik: string;
  deger: number;
}

type ElemanTipi<T> = T extends readonly (infer E)[] ? E : never;

declare const eleman: ElemanTipi<Olcum[]>;
declare const dizgiEleman: ElemanTipi<readonly string[]>;
declare const dizisiz: ElemanTipi<number>;

const a: null = eleman;
const b: null = dizgiEleman;
const c: null = dizisiz;
```

```text
p3.ts(12,7): error TS2322: Type 'Olcum' is not assignable to type 'null'.
p3.ts(13,7): error TS2322: Type 'string' is not assignable to type 'null'.
```

`ElemanTipi<Olcum[]>` tipi `Olcum`, `ElemanTipi<readonly string[]>` tipi `string` olmuştur.
On dördüncü satırın tanı vermemesi de bilgi taşır: `ElemanTipi<number>` tipi `never`dir ve
`never` her tipe — `null` dahil — atanabilir.

Aynı teknik, kursun sonuç tipinden yük tipini çıkarmak için kullanılır:

```typescript
interface Olcum {
  kimlik: string;
  deger: number;
}

type Sonuc<D, H = string> =
  | { durum: "basarili"; deger: D }
  | { durum: "hatali"; hata: H };

type BasariTipi<S> = S extends { durum: "basarili"; deger: infer D } ? D : never;
type HataTipi<S> = S extends { durum: "hatali"; hata: infer H } ? H : never;

declare const basari: BasariTipi<Sonuc<Olcum>>;
declare const hata: HataTipi<Sonuc<Olcum, number>>;

const a: null = basari;
const b: null = hata;
```

```text
p4.ts(16,7): error TS2322: Type 'Olcum' is not assignable to type 'null'.
p4.ts(17,7): error TS2322: Type 'number' is not assignable to type 'null'.
```

Dağılım burada da iş görüyor: `Sonuc<Olcum>` iki üyeli bir birleşimdir; `BasariTipi`
hesabında başarı üyesi `Olcum`, hata üyesi `never` verir ve birleşim `Olcum`a indirgenir.

Bu kalıbın değeri, bir tipin **tanımını tekrarlamadan** parçasına erişebilmektir. `Sonuc`
tipinin yapısı değişirse `BasariTipi` da değişir; ikisi arasında elle tutulan bir bağ
kalmaz.

## Koşullu Dönüş Tipinin Sınırı

Koşullu tipler fonksiyon imzalarında kullanılabilir, ancak gövde içinde çözülmezler:

```typescript
type Bicim<T> = T extends number ? string : number;

function bicimle<T extends number | boolean>(deger: T): Bicim<T> {
  if (typeof deger === "number") {
    return deger.toFixed(1);
  }
  return 0;
}

console.log(bicimle(21.4), bicimle(true));
```

```text
p7.ts(5,5): error TS2322: Type 'string' is not assignable to type 'Bicim<T>'.
p7.ts(7,3): error TS2322: Type 'number' is not assignable to type 'Bicim<T>'.
```

Gövde içinde `T` henüz bilinmediği için `Bicim<T>` çözülemez; derleyici, `typeof deger`
sınamasının `T`yi de daralttığını çıkaramaz. Tanı iki dalda birden gelir.

Bu, tip sisteminin bilinen bir sınırıdır. İki çözüm vardır: gövdede tek bir tip iddiası
kullanmak — sınırı görünür kılan, imzada verilen sözü gövdenin taşıdığını kabul eden bir
borç — ya da koşullu tip yerine aşırı yükleme yazmak. İkincisi, Fonksiyon Tipleri dersinde
kurulan yapıdır ve çağıranlar için aynı sonucu verir.

Genel ilke: koşullu tipler **tip hesaplamak** için güçlüdür, **gerçekleştirimi
yönlendirmek** için değil.

## Özet

- Koşullu tip, atanabilirlik sınamasına göre iki tipten birini seçer; `extends` burada
  kalıtım değil atanabilirlik anlamındadır.
- Çıplak bir tip parametresi birleşimse koşul her üye için ayrı değerlendirilir ve
  sonuçların birleşimi alınır; `[T] extends [U]` yazımı bu dağılımı kapatır.
- Dağılım ve `never` birlikte, bir birleşimden üye eleyen süzgeçler kurar.
- `infer`, koşulun sol tarafında bir tip değişkeni bildirir ve eşleştirme sırasında ona
  karşılık gelen tipi çıkarır; bir tipin parçasına tanımı tekrarlamadan erişmeyi sağlar.
- Koşullu dönüş tipleri fonksiyon gövdesi içinde çözülmez; bu durumda tip iddiası ya da
  aşırı yükleme gerekir.

## Sonraki Adım

Anahtar yeniden eşlemesi dersinde `` `oku${Capitalize<string & A>}` `` biçiminde bir yazım
kullanıldı ve alan adı hesaplandı. Dizgilerin tip düzeyinde birleştirilmesi ve
ayrıştırılması ayrı bir araç kümesidir. Sonraki ders şablon dizgi tiplerini ve bunların
`infer` ile birlikte dizgi biçimlerini çözümlemekte nasıl kullanıldığını ele alacak.
