- Birleşim (
A | B) ve kesişim (A & B) tiplerini yazmak ve ayırt etmek - Bir tipi
typeof,in,===venullkontrolüyle daraltmak - Ayırt edici bir birleşim kurmak ve tüm durumların ele alındığını
neverile denetlemek value is Tbiç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:
function shout(id: number | string): string {
return id.toUpperCase();
}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();
~~~~~~~~~~~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.
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'));#0042 AB-17
if içinde id bir number'dır; return'den sonra geriye yalnızca string kalır.Daraltma araçları
| Kontrol | Ne zaman kullanılır |
|---|---|
typeof x === 'string' | ilkel tipler: string, number, boolean vb. |
x === null | null ya da undefined'ı ayırmak |
'cardNumber' in x | farklı özelliklere sahip nesneler |
x instanceof Date | sınıf örnekleri |
x.kind === 'circle' | ayırt edici birleşimler (aşağıda) |
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'));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.
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));
}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:
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;
}
}
}area.ts:13:13 - error TS2322: Type '{ kind: "triangle"; base: number; height: number; }' is not assignable to type 'never'.
13 const unhandled: never = shape;
~~~~~~~~~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:
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(', '));BAKU, GANJA, SHAKI
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:
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})`);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,===,inveinstanceofkontrolleri dalın içinde tipi daraltır.- Ayırt edici birleşimde her üyenin
kindgibi literal bir özelliği vardır;switchonu kusursuz daraltır. defaultdalındanevertipine atama, unutulan durumları derleme sırasında bulur.value is Tdöndüren fonksiyon bir tip korumasıdır;A & Bise iki tipin tüm özelliklerini birleştirir.
Kendini test et
10 soru. Her doğru cevap XP kazandırır.
if (typeof id === 'number') { ... } bloğunun içinde id: number | string parametresinin tipi nedir?