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

# Eşlenmiş Tipler

Var olan bir tipten yeni tip üretme; alan değiştiricilerinin eklenmesi ve kaldırılması, anahtar yeniden eşlemesi, alan süzme ve eşlemenin dizi ile demetler üzerindeki davranışı.

Ölçüm kaydının değişik biçimleri şimdiye kadar elle yazıldı: arşivlenmiş kayıtlar için
salt okunur bir sürüm, güncelleme isteği için alanları seçmeli bir sürüm, listeleme için
yalnızca birkaç alanı taşıyan bir özet.

Her biri asıl tipin bir dönüşümüdür. Elle yazıldıklarında asıl tip değiştiğinde birlikte
güncellenmeleri gerekir ve bu, unutulmaya elverişli bir bakım borcudur. **Eşlenmiş tip**
(mapped type), dönüşümü tip düzeyinde hesaplar: alan listesi tek yerde durur, türevler
kendiliğinden güncellenir.

## Temel Yazım

Eşlenmiş tip, bir anahtar kümesi üzerinde dolaşan bir döngüye benzer:

```typescript
interface Olcum {
  kimlik: string;
  deger: number;
  birim: "C" | "Pa" | "%";
}

type SaltOkunur<T> = { readonly [A in keyof T]: T[A] };
type Yamalanabilir<T> = { [A in keyof T]?: T[A] };

const arsivKayit: SaltOkunur<Olcum> = {
  kimlik: "s-01",
  deger: 21.4,
  birim: "C",
};
console.log(arsivKayit.deger);

const yama: Yamalanabilir<Olcum> = { deger: 22.1 };
console.log(yama.deger, yama.kimlik);
```

Çıktı:

```text
21.4
22.1 undefined
```

Dosyanın sonuna, bir boş satırdan sonra `arsivKayit.deger = 22.1;` satırı eklenirse:

```text
o2.ts(20,12): error TS2540: Cannot assign to 'deger' because it is a read-only property.
```

Yazımın parçaları şunlardır. `[A in keyof T]` bölümü, `keyof T` birleşiminin her üyesini
sırayla `A` adına bağlar — Programlama Temelleri kursundaki `for` döngüsünün tip
düzeyindeki karşılığı. İki nokta üstündeki `T[A]`, o alanın asıl tipidir. Başa yazılan
`readonly` ve ada eklenen `?`, her alana uygulanan **değiştiricilerdir**.

`Yamalanabilir<Olcum>` tipinin bütün alanları seçmeli olduğu için `{ deger: 22.1 }` sabiti
kabul edilir; `yama.kimlik` erişiminin tipi `string | undefined`dır ve çıktıda `undefined`
görünür.

Bu iki dönüşümün karşılığı standart kitaplıkta zaten bulunur (`Readonly` ve `Partial`);
Yardımcı Tipler dersinde ele alınacaklardır. Burada elle yazılmalarının nedeni,
mekanizmanın görünür olmasıdır.

## Değiştirici Kaldırma

Değiştiriciler eklenebildiği gibi kaldırılabilir de. Kaldırma, değiştiricinin önüne eksi
işareti konarak yazılır:

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

type Cozulmus<T> = { -readonly [A in keyof T]-?: T[A] };

const tam: Cozulmus<Olcum> = { kimlik: "s-01", deger: 21.4 };
tam.deger = 22.1;
console.log(tam.deger.toFixed(1));
```

Çıktı `22.1`dir. Dosyanın sonuna, bir boş satırdan sonra
`const eksik: Cozulmus<Olcum> = { kimlik: "s-02" };` satırı eklenirse:

```text
o4.ts(12,7): error TS2741: Property 'deger' is missing in type '{ kimlik: string; }' but required in type 'Cozulmus<Olcum>'.
```

`Olcum` tipinde `kimlik` salt okunur, `deger` hem salt okunur hem seçmeliydi.
`Cozulmus<Olcum>` tipinde ikisi de yazılabilir ve zorunludur. `tam.deger.toFixed(1)`
çağrısının daraltma gerektirmemesi bunun sonucudur: alan artık `number`dır,
`number | undefined` değil.

Bu dönüşümün kullanım yeri, kısmi bir kaydın tamamlanmış hâlini temsil etmektir.
Varsayılan değerler uygulandıktan sonra elde edilen kayıt için ayrı bir tip yazmak yerine,
asıl tipten hesaplanır.

## Anahtar Yeniden Eşlemesi

`as` yazımı, üretilen alanın adını değiştirmeyi sağlar:

```typescript
interface Olcum {
  kimlik: string;
  deger: number;
  birim: "C" | "Pa" | "%";
}

type Okuyucular<T> = {
  [A in keyof T as `oku${Capitalize<string & A>}`]: () => T[A];
};

const okuyucu: Okuyucular<Olcum> = {
  okuKimlik: () => "s-01",
  okuDeger: () => 21.4,
  okuBirim: () => "C",
};

console.log(okuyucu.okuDeger().toFixed(1), okuyucu.okuKimlik());
```

Çıktı `21.4 s-01`dir.

Üretilen tip, her alan için bir okuyucu fonksiyon bildirir ve dönüş tipini asıl alandan
alır: `okuDeger` çağrısı `number`, `okuBirim` çağrısı `"C" | "Pa" | "%"` verir. Ad
üretiminde kullanılan şablon dizgi yazımı ile `Capitalize` dönüşümü sonraki dersin
konusudur; burada yalnızca adın hesaplanabildiği görülmelidir.

Yeniden eşlemenin ikinci ve daha güçlü kullanımı, bir alanı **elemektir**. Üretilen ad
`never` olduğunda o alan çıktıya girmez:

```typescript
interface Olcum {
  kimlik: string;
  deger: number;
  birim: "C" | "Pa" | "%";
  zaman: number;
}

type SayisalAlanlar<T> = {
  [A in keyof T as T[A] extends number ? A : never]: T[A];
};

const sayisal: SayisalAlanlar<Olcum> = { deger: 21.4, zaman: 1706000000000 };
console.log(sayisal.deger + sayisal.zaman);
```

Çıktı `1706000000021.4`tür. Dosyanın sonuna, bir boş satırdan sonra
`const yanlis: SayisalAlanlar<Olcum> = { deger: 21.4, zaman: 1, kimlik: "s-01" };` satırı
eklenirse:

```text
o7.ts(15,64): error TS2353: Object literal may only specify known properties, and 'kimlik' does not exist in type 'SayisalAlanlar<Olcum>'.
```

Sonuç tipi yalnızca `deger` ve `zaman` alanlarını taşır; `kimlik` ve `birim` elenmiştir.
`T[A] extends number ? A : never` yazımı bir **koşullu tiptir** ve sonraki derslerden
birinin konusudur; burada işlevi, alan tipine bakarak adı tutmak veya `never` üretip
elemektir.

Bu tip, ölçüm kaydının sayısal özetini çıkaran kodun imzasında kullanılabilir. Kayda yeni
bir sayısal alan eklendiğinde özet tipi kendiliğinden büyür; dizgi bir alan eklendiğinde
etkilenmez.

## Diziler ve Demetler Üzerinde Eşleme

`keyof T` üzerinde dolaşan bir eşleme diziye uygulandığında beklenmedik bir şey **olmaz**:
sonuç yine bir dizidir.

```typescript
type SaltOkunur<T> = { readonly [A in keyof T]: T[A] };

const degerler: SaltOkunur<number[]> = [21.4, 22.1];
const aralik: SaltOkunur<[alt: number, ust: number]> = [-40, 85];

console.log(degerler.length, degerler[0], aralik[1]);
console.log(degerler.map((d) => d * 2));
```

Çıktı:

```text
2 21.4 85
[ 42.8, 44.2 ]
```

`SaltOkunur<number[]>` tipi `readonly number[]`, `SaltOkunur<[number, number]>` tipi salt
okunur bir demettir. Dizi yöntemleri (`map`, `length`, indeksli erişim) kullanılabilir
durumda kalmış, değiştirme yöntemleri kalkmıştır:

```typescript
type SaltOkunur<T> = { readonly [A in keyof T]: T[A] };

const degerler: SaltOkunur<number[]> = [21.4, 22.1];
degerler.push(23.0);
```

```text
u4.ts(4,10): error TS2339: Property 'push' does not exist on type 'readonly number[]'.
```

Bu davranış, eşlemenin kaynağı **doğrudan** `keyof T` olduğunda geçerlidir. Derleyici bu
biçimi tanır ve dizi ile demetleri kendi türlerinde tutar. Kaynak başka bir ifadeyle
yazıldığında tanıma bozulur:

```typescript
type EslemA<T> = { readonly [A in keyof T]: T[A] };
type EslemB<T> = { readonly [A in keyof T & string]: T[A] };

declare const a: EslemA<number[]>;
declare const b: EslemB<number[]>;

const x: null = a;
const y: null = b;
```

```text
u11.ts(7,7): error TS2322: Type 'readonly number[]' is not assignable to type 'null'.
u11.ts(8,7): error TS2322: Type 'EslemB<number[]>' is not assignable to type 'null'.
```

Tanıların farkı belirleyicidir. `EslemA<number[]>` tipi `readonly number[]` olarak
çözülmüştür — derleyici sonucu bir dizi olarak yazıyor. `EslemB<number[]>` ise
çözülmemiş bir eşleme olarak kalmıştır; dizi yapısı kaybolmuş, yerine dizinin özellik
adlarını taşıyan sıradan bir nesne tipi geçmiştir.

Pratik kural: **bir tipin yapısını korumak isteniyorsa eşleme kaynağı `keyof T` olarak
yazılır.** Anahtar süzmek gerekiyorsa süzme, `as` yeniden eşlemesiyle yapılır — kaynak
`keyof T` kalır, ad hesabı sağ tarafta olur.

## Herhangi Bir Birleşim Üzerinde Eşleme

Eşleme kaynağının `keyof T` olması zorunlu değildir; herhangi bir dizgi birleşimi
kullanılabilir:

```typescript
type Birim = "C" | "Pa" | "%";

type Araliklar = {
  [B in Birim]: [alt: number, ust: number];
};

const araliklar: Araliklar = {
  C: [-40, 85],
  Pa: [0, 200000],
  "%": [0, 100],
};

console.log(araliklar.C[1], araliklar["%"][1]);
```

Çıktı `85 100`dür. Dosyanın sonuna, bir boş satırdan sonra
`const eksik: Araliklar = { C: [-40, 85], Pa: [0, 200000] };` satırı eklenirse:

```text
o9.ts(15,7): error TS2741: Property '"%"' is missing in type '{ C: [number, number]; Pa: [number, number]; }' but required in type 'Araliklar'.
```

Bu, Arayüzler dersinde eleştirilen indeks imzasının doğru alternatifidir. İndeks imzası
"her dizgi anahtar geçerlidir" der ve olmayan anahtara erişimi hata saymazdı. Eşlenmiş tip
ise anahtar kümesini **tam olarak** belirler: eksik bir anahtar tanı verir, fazladan bir
anahtar da öyle.

Değer kümesi `Birim` birleşimine yeni bir birim eklendiğinde, aralık tablosunu güncellemek
zorunlu hâle gelir. Ayırt edici birleşimde `never` ile kurulan tükenmişlik denetiminin,
veri tabloları için karşılığıdır.

## Özet

- Eşlenmiş tip, bir anahtar kümesi üzerinde dolaşarak yeni bir nesne tipi üretir; türev
  tipler asıl tiple birlikte güncellenir.
- `readonly` ve `?` değiştiricileri eşleme sırasında eklenebilir; `-readonly` ve `-?`
  yazımlarıyla kaldırılabilir.
- `as` yazımı üretilen alanın adını hesaplar; ad `never` olduğunda alan çıktıdan elenir.
- Eşleme kaynağı `keyof T` olmak zorunda değildir; herhangi bir dizgi birleşimi üzerinde
  eşleme yapılabilir.
- Eşleme kaynağı doğrudan `keyof T` olduğunda dizi ve demetler kendi türlerinde kalır;
  kaynak başka bir ifadeyle yazıldığında bu yapı kaybolur.
- Sabit anahtar kümesi için eşlenmiş tip, indeks imzasından güvenlidir: eksik ve fazla
  anahtarların ikisi de bildirilir.

## Sonraki Adım

Önceki iki örnekte `T[A] extends number ? A : never` biçiminde bir yazım geçti ve tip
düzeyinde bir dallanma yaptı. Bu, tip sisteminin hesaplama yeteneğinin merkezindeki
yapıdır. Sonraki ders koşullu tipleri, dağılım kurallarını ve bir tipin içinden parça
çıkaran `infer` yazımını ele alacak.
