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

# Özyinelemeli Tipler

Kendine başvuran tip tanımları, derin dönüşümler, tip düzeyinde özyineleme ile anahtar yolu üretimi ve derleyicinin açılım derinliği sınırı.

Ölçüm kayıtları her zaman düz bir yapı taşımaz: bir kaydın altında alt kayıtlar, bir
yapılandırma nesnesinin altında iç içe bölümler bulunur. Böyle yapıların tipi, kendisine
başvurmak zorundadır.

Tip Takma Adları dersinde bu olanağın sınırı belirlenmişti: nesne alanı içindeki başvuru
geçerli, doğrudan başvuru geçersizdi. Bu ders, o olanağın ne kadar ileri götürülebileceğini
— derin dönüşümler ve tip düzeyinde özyineleme — ve derleyicinin nerede durduğunu ele
alır.

## Kendine Başvuran Veri Tipleri

Yapısı önceden bilinmeyen, iç içe geçebilen veri için tipik örnek JSON'un kendisidir:

```typescript
type JsonDegeri =
  | string
  | number
  | boolean
  | null
  | JsonDegeri[]
  | { [anahtar: string]: JsonDegeri };

function derinlik(deger: JsonDegeri): number {
  if (Array.isArray(deger)) {
    return 1 + Math.max(0, ...deger.map(derinlik));
  }
  if (typeof deger === "object" && deger !== null) {
    return 1 + Math.max(0, ...Object.values(deger).map(derinlik));
  }
  return 0;
}

const kayit: JsonDegeri = {
  kimlik: "s-01",
  deger: 21.4,
  etiketler: ["kazan", "vardiya-3"],
  konum: { bina: "A", kat: 2 },
};

console.log(derinlik(kayit));
console.log(derinlik(21.4));
```

Çıktı:

```text
2
0
```

Tip, altı üyeli bir birleşimdir ve son iki üyesi kendisine başvurur. Başvurular birer
alan tipi içinde olduğu için derleyici onları yalnızca gerektiğinde çözer; sonsuz açılım
oluşmaz.

Tipin bir güvencesi de vardır. Dosyanın sonuna, bir boş satırdan sonra
`const gecersiz: JsonDegeri = { zaman: new Date() };` satırı eklenirse:

```text
s1.ts(29,7): error TS2322: Type '{ zaman: Date; }' is not assignable to type 'JsonDegeri'.
  Types of property 'zaman' are incompatible.
    Type 'Date' is not assignable to type 'JsonDegeri | undefined'.
      Type 'Date' is not assignable to type '{ [anahtar: string]: JsonDegeri; }'.
        Index signature for type 'string' is missing in type 'Date'.
```

Bu, dizileştirilebilir veriyi dizileştirilemeyenden ayıran bir sınamadır. `JSON.stringify`
çağrısı bir tarih nesnesini sessizce dizgiye çevirir ve ayrıştırma sonrası tip değişir;
`JsonDegeri` tipi bu sessiz dönüşümü derleme anına taşır.

`derinlik` fonksiyonu da özyinelemelidir ve tipin yapısını izler: Programlama Temelleri
kursundaki özyineleme dersinde kurulan taban durumu ile indirgeme adımı, burada tipin
üyelerine karşılık gelir.

## Derin Dönüşümler

Yardımcı tipler dersindeki `Readonly` yalnızca birinci düzeye uygulanır:

```typescript
interface Yapilandirma {
  ad: string;
  esikler: { alt: number; ust: number };
}

const sig: Readonly<Yapilandirma> = {
  ad: "kazan-2",
  esikler: { alt: -40, ust: 85 },
};

sig.esikler.ust = 90;
console.log(sig.esikler.ust);
```

Bu dosya tip denetiminden **geçer** ve `90` yazar. `sig.esikler` alanı salt okunurdur,
ancak işaret ettiği nesnenin alanları değildir.

Özyinelemeli bir eşlenmiş tip bu boşluğu kapatır:

```typescript
type DerinSaltOkunur<T> = {
  readonly [A in keyof T]: T[A] extends object ? DerinSaltOkunur<T[A]> : T[A];
};

interface Yapilandirma {
  ad: string;
  esikler: { alt: number; ust: number };
  kanallar: { sensor: string; birim: string }[];
}

const yapilandirma: DerinSaltOkunur<Yapilandirma> = {
  ad: "kazan-2",
  esikler: { alt: -40, ust: 85 },
  kanallar: [{ sensor: "sicaklik", birim: "C" }],
};

console.log(yapilandirma.esikler.ust, yapilandirma.kanallar[0].sensor);
```

Çıktı `85 sicaklik`tır. Dosyanın sonuna, bir boş satırdan sonra
`yapilandirma.esikler.ust = 90;` satırı eklenirse:

```text
s3.ts(19,22): error TS2540: Cannot assign to 'ust' because it is a read-only property.
```

Eşleme her alanda `T[A] extends object` koşulunu sınar; nesne olan alanlarda kendini
yeniden uygular, ilkel alanlarda durur. Diziler de nesne olduğu için `kanallar` alanı
`readonly` bir diziye dönüşür ve elemanlarının alanları da salt okunur olur.

Önceki derslerdeki uyarı yine geçerlidir: bu güvence derleme anına aittir. Yapılandırma
nesnesi çalışma zamanında değiştirilebilir; derinlemesine dondurmak ayrı bir işlemdir.

## Tip Düzeyinde Özyineleme

Özyineleme yalnızca veri biçimi tanımlamakla sınırlı değildir; tip düzeyinde hesap yapmak
için de kullanılır. İç içe bir nesnenin tüm anahtar yollarını üreten tip, bunun tipik
örneğidir:

```typescript
type Yol<T> = T extends object
  ? {
      [A in keyof T & string]: T[A] extends object ? A | `${A}.${Yol<T[A]>}` : A;
    }[keyof T & string]
  : never;

interface Yapilandirma {
  ad: string;
  esikler: { alt: number; ust: number };
  ag: { adres: string; kimlik: { kullanici: string } };
}

const gecerli: Yol<Yapilandirma>[] = [
  "ad",
  "esikler",
  "esikler.alt",
  "ag.kimlik.kullanici",
];
console.log(gecerli.length);
```

Çıktı `4`tür. Dosyanın sonuna, bir boş satırdan sonra
`const yanlisYol: Yol<Yapilandirma> = "esikler.orta";` satırı eklenirse:

```text
s6.ts(21,7): error TS2322: Type '"esikler.orta"' is not assignable to type '"ad" | "esikler" | "ag" | "esikler.alt" | "esikler.ust" | "ag.adres" | "ag.kimlik" | "ag.kimlik.kullanici"'.
```

Tanı, hesabın tam sonucunu yazıyor: sekiz geçerli yol. Yapı üç dersin bileşimidir. Eşlenmiş
tip her alan için bir değer üretir; `[keyof T & string]` indeksli erişimi bu değerlerin
birleşimini alır; şablon dizgi tipi alt yolları öne eklenmiş ad ile birleştirir; koşullu
tip nesne olmayan alanlarda özyinelemeyi durdurur.

Bu tipin kullanım yeri, yapılandırma anahtarını dizgi olarak alan bir arayüzdür. Yol
dizgisi artık serbest bir dizgi değil, kapalı bir kümedir; yanlış yazılmış bir anahtar
derleme anında yakalanır.

## Derinlik Sınırı

Derleyici sonsuz açılımı önlemek için bir üst sınır uygular. Sınır, uzunluğu sayan bir
demet kurarak gözlenebilir:

```typescript
type Yinele<N extends number, B extends unknown[] = []> = B["length"] extends N
  ? B
  : Yinele<N, [...B, unknown]>;

type Sonuc = Yinele<1001>;
declare const s: Sonuc;
console.log(s.length);
```

```text
s10.ts(5,14): error TS2589: Type instantiation is excessively deep and possibly infinite.
```

Aynı dosyada `Yinele<999>` yazıldığında tanı gelmez. Sınırın tam değeri derleyici sürümüne
bağlıdır ve buna dayanan kod kırılgandır; önemli olan **bir sınırın bulunmasıdır**.

Sınırın altında kalan özyinelemelerin de bir bedeli vardır: her açılım derleyicinin
çalışma süresini artırır. Yol üretimi gibi tipler, geniş yapılandırma nesnelerinde tip
denetimini gözle görülür biçimde yavaşlatabilir. Algoritmalar kursundaki zaman ve alan
ödünleşimi burada derleme süresi ile tip kesinliği arasında kurulur.

Sınırsız derinlik gerektiren durumlar için tip düzeyi çözüm uygun değildir; doğru araç,
çalışma zamanı doğrulaması ve markalı tiptir.

## Özyineleme Yazarken

Üç kural, özyinelemeli tiplerin sağlıklı kalmasını sağlar.

**Taban durumu açık yazılır.** Yukarıdaki her örnekte özyinelemenin durduğu bir koşul
vardır: `JsonDegeri` için ilkel üyeler, `DerinSaltOkunur` için `extends object` sınaması,
`Yol` için aynı sınama. Taban durumu olmayan bir tip, derleyicinin sınırına kadar açılır ve
`TS2589` verir.

**Derinlik veriden gelmemelidir.** Açılım derinliği tipin yapısına bağlı olmalı, çağıranın
verdiği bir sayıya değil. `Yinele<N>` örneği bilinçli olarak bu kuralı çiğneyerek sınırı
gösterir.

**Sonuç sınanır.** Tip düzeyinde hesaplanan bir tipin doğruluğu, beklenen değerleri içeren
bir dizi bildirerek sınanabilir — yukarıdaki `gecerli` bildirimi bunu yapar. Yanlış
hesaplanan bir tip, kullanıldığı her yerde şaşırtıcı tanılar üretir.

## Özet

- Nesne alanı içindeki kendine başvuru geçerlidir; derleyici bu başvuruları yalnızca
  gerektiğinde çözer.
- `Readonly` gibi yardımcı tipler yalnızca birinci düzeye uygulanır; derin dönüşüm için
  özyinelemeli eşlenmiş tip yazılır.
- Eşlenmiş tip, indeksli erişim, şablon dizgi tipi ve koşullu tip birlikte, iç içe
  anahtar yollarını kapalı bir birleşim olarak üretebilir.
- Derleyici belirli bir açılım derinliğinden sonra `TS2589` tanısı verir; sınırın değeri
  sürüme bağlıdır ve ona dayanan kod kırılgandır.
- Özyinelemeli tipte taban durumu açıkça yazılır, derinlik veriden değil yapıdan gelir ve
  sonuç ayrı bir bildirimle sınanır.

## Sonraki Adım

Buraya kadar tüm örnekler tek dosyalık ve elle verilmiş derleyici seçenekleriyle çalıştı.
Gerçek bir projede seçenekler bir yapılandırma dosyasında toplanır ve katılık düzeyi
bilinçli seçilir. Sonraki konu proje yapılandırmasını ele alacak: hangi bayrağın hangi hata
sınıfını yakaladığı, bildirim dosyalarının rolü, JavaScript ile birlikte çalışma ve tip
denetimi ile yayın çıktısının ayrılması.
