İçeriğe geç
Educora
Orta18 dk5 / 8

Birleşim tipleri ve daraltma

Tipleri `|` ve `&` ile birleştir; `typeof`, `in` ve karşılaştırmalarla daralt, ayırt edici birleşimler kur ve kendi tip korumalarını yaz.

Kendini test et
Bu derste öğreneceklerin
  • Birleşim (A | B) ve kesişim (A & B) tiplerini yazmak ve ayırt etmek
  • Bir tipi typeof, in, === ve null kontrolüyle daraltmak
  • Ayırt edici bir birleşim kurmak ve tüm durumların ele alındığını never ile denetlemek
  • value is T biçiminde bir tip koruması yazmak

Gerçek hayatta değerler çoğu zaman birkaç biçimde gelir. Bir sipariş numarası 42 de olabilir, 'AB-17' de. Ödeme ya kartla ya da nakit yapılır. Sunucu ya veriyi ya da bir hata mesajını döndürür. Bu durumları tek bir tiple tanımlayamazsın; “bu veya şu” gerekir. TypeScript bunun için birleşim tiplerini, onlarla güvenle çalışmak için de daraltmayı sunar.

Birleşim tipleri

number | string tipi “ya bir sayı ya da bir string” demektir. Böyle bir değerle yalnızca birleşimin tüm üyelerinde geçerli olan işlemler yapılabilir. Sayının toUpperCase metodu olmadığı için şu kod hatalıdır:

TypeScript
function shout(id: number | string): string {
  return id.toUpperCase();
}
Text
ids.ts:2:13 - error TS2339: Property 'toUpperCase' does not exist on type 'string | number'.
  Property 'toUpperCase' does not exist on type 'number'.

2   return id.toUpperCase();
              ~~~~~~~~~~~
Tanım
Daraltma

Derleyicinin kontrollerini (typeof, in, ===, instanceof vb.) izleyerek bir if ya da switch dalının içinde değerin tipini kesinleştirmesi. Dalın içinde birleşimden yalnızca uygun üye kalır.

TypeScript
function formatId(id: number | string): string {
  if (typeof id === 'number') {
    return `#${id.toString().padStart(4, '0')}`;
  }
  return id.toUpperCase();
}

console.log(formatId(42));
console.log(formatId('ab-17'));
Beklenen çıktı
#0042
AB-17
if içinde id bir number'dır; return'den sonra geriye yalnızca string kalır.

Daraltma araçları

KontrolNe zaman kullanılır
typeof x === 'string'ilkel tipler: string, number, boolean vb.
x === nullnull ya da undefined'ı ayırmak
'cardNumber' in xfarklı özelliklere sahip nesneler
x instanceof Datesınıf örnekleri
x.kind === 'circle'ayırt edici birleşimler (aşağıda)
TypeScript
type Card = { cardNumber: string };
type Cash = { amount: number };

function describePayment(p: Card | Cash): string {
  if ('cardNumber' in p) {
    return `Card ending in ${p.cardNumber.slice(-4)}`;
  }
  return `Cash: ${p.amount} AZN`;
}

function greet(name: string | null): string {
  if (name === null) {
    return 'Hello, guest!';
  }
  return `Hello, ${name}!`;
}

console.log(describePayment({ cardNumber: 'XXXX-XXXX-XXXX-4821' }));
console.log(describePayment({ amount: 20 }));
console.log(greet(null), greet('Leyla'));
Beklenen çıktı
Card ending in 4821
Cash: 20 AZN
Hello, guest! Hello, Leyla!

Ayırt edici birleşimler

En güçlü yöntem, birleşimin her üyesine aynı adlı ama farklı literal değerli bir özellik vermektir; genellikle kind ya da type. Bu özelliğe ayırt edici (discriminant) denir. switch (shape.kind) yazdığında her case içinde TypeScript şeklin tam türünü bilir ve yalnızca onun özelliklerine izin verir.

TypeScript
type Shape =
  | { kind: 'circle'; radius: number }
  | { kind: 'square'; side: number }
  | { kind: 'rectangle'; width: number; height: number };

function area(shape: Shape): number {
  switch (shape.kind) {
    case 'circle':
      return Math.PI * shape.radius ** 2;
    case 'square':
      return shape.side ** 2;
    case 'rectangle':
      return shape.width * shape.height;
  }
}

const shapes: Shape[] = [
  { kind: 'circle', radius: 1 },
  { kind: 'square', side: 3 },
  { kind: 'rectangle', width: 2, height: 5 },
];

for (const s of shapes) {
  console.log(s.kind, area(s).toFixed(2));
}
Beklenen çıktı
circle 3.14
square 9.00
rectangle 10.00

Yarın ekipten biri birleşime bir üçgen eklerse ne olur? Tüm durumların ele alındığını garanti etmek için default dalında değer never tipinde bir değişkene atanır. never, “hiçbir değer” demektir: tüm durumlar ele alındıysa oraya hiçbir şey ulaşmaz. Ele alınmamış bir durum kaldıysa derleyici hemen haber verir:

TypeScript
type Shape =
  | { kind: 'circle'; radius: number }
  | { kind: 'square'; side: number }
  | { kind: 'triangle'; base: number; height: number };

function area(shape: Shape): number {
  switch (shape.kind) {
    case 'circle':
      return Math.PI * shape.radius ** 2;
    case 'square':
      return shape.side ** 2;
    default: {
      const unhandled: never = shape;
      return unhandled;
    }
  }
}
Text
area.ts:13:13 - error TS2322: Type '{ kind: "triangle"; base: number; height: number; }' is not assignable to type 'never'.

13       const unhandled: never = shape;
               ~~~~~~~~~
Hata mesajı hangi durumun unutulduğunu tam olarak gösterir: üçgen.

Kendi tip korumaların

Bir kontrolü ayrı bir fonksiyona taşımak istersen düz bir boolean döndürmek yetmez; TypeScript sonuç çıkarmak için fonksiyonun içine bakmaz. Dönüş tipini value is string olarak yazdığında fonksiyon bir tip korumasına (type guard) dönüşür: true döndürürse derleyici değerin string olduğuna güvenir. Bu özellikle filter ile çok kullanışlıdır:

TypeScript
function isString(value: unknown): value is string {
  return typeof value === 'string';
}

const inputs: unknown[] = ['Baku', 42, 'Ganja', null, 'Shaki'];
const cities = inputs.filter(isString);

console.log(cities.map((city) => city.toUpperCase()).join(', '));
Beklenen çıktı
BAKU, GANJA, SHAKI
Koruma sayesinde cities'in tipi unknown[] değil string[] olur ve toUpperCase çağrılabilir.

Kesişim tipleri

Birleşim “bunlardan biri” demekse kesişim A & B, “hepsi birden” demektir: değer iki tipin de tüm özelliklerine sahip olmalıdır. Kesişimlerle küçük, yeniden kullanılabilir parçalardan büyük tipler kurmak kolaydır:

TypeScript
type HasId = { id: number };
type HasDate = { createdAt: string };
type Post = HasId & HasDate & { title: string };

const post: Post = { id: 1, createdAt: '2025-09-01', title: 'Hello, TypeScript' };
console.log(`${post.id}: ${post.title} (${post.createdAt})`);
Beklenen çıktı
1: Hello, TypeScript (2025-09-01)

Önemli noktalar

  • A | B, “ya A ya B” demektir; doğrudan yalnızca tüm üyelerde ortak olan özellikler kullanılabilir.
  • typeof, ===, in ve instanceof kontrolleri dalın içinde tipi daraltır.
  • Ayırt edici birleşimde her üyenin kind gibi literal bir özelliği vardır; switch onu kusursuz daraltır.
  • default dalında never tipine atama, unutulan durumları derleme sırasında bulur.
  • value is T döndüren fonksiyon bir tip korumasıdır; A & B ise iki tipin tüm özelliklerini birleştirir.

Kendini test et

10 soru. Her doğru cevap XP kazandırır.

1 / 10
if (typeof id === 'number') { ... } bloğunun içinde id: number | string parametresinin tipi nedir?