TypeScript'te narrowing (daraltma), derleyicinin kodunuzdaki kontrollere bakarak bir değişkenin tipini o noktada daha dar bir tipe indirmesidir. typeof, doğruluk (truthiness) kontrolü, === ve != karşılaştırmaları, in, instanceof, atamalar, kendi yazdığınız x is T dönüşlü fonksiyonlar (type predicate) ve asserts imzalı fonksiyonlar bu işi yapar. Bu kontrollerin her birine type guard denir. Tüm olasılıklar elendiğinde kalan tip never olur ve bu, eksik durumları yakalamak için kullanılır.
Aşağıda her tekniği küçük bir örnekle ve hangi tuzağa düşebileceğinizle birlikte anlatıyoruz. Örnekler TypeScript 6.0.3 ile tsc --strict --target es2022 --moduleDetection force seçenekleriyle derlendi; hata kodları ve mesajları bu derleyicinin gerçek çıktısıdır. TypeScript 6.0'da strict varsayılan olarak açık geldiği için null ve undefined ayrı tipler olarak ele alınır; örneklerdeki "possibly null" hataları bu yüzden görünür. Konunun temeli olan union tipleri için union ve intersection yazısına bakabilirsiniz.
Daraltma nasıl çalışır?

Derleyici kodunuzu yalnızca satır satır okumaz; programın izleyebileceği yolları da takip eder. Buna control flow analysis (kontrol akışı analizi) denir. Bir if dalında return ettiğinizde, fonksiyonun geri kalanında o dalın koşulunun sağlanmadığını bilir:
function solaDoldur(dolgu: number | string, metin: string): string {
if (typeof dolgu === "number") {
return " ".repeat(dolgu) + metin; // dolgu: number
}
return dolgu + metin; // dolgu: string
}
console.log("[" + solaDoldur(3, "ts") + "]"); // [ ts]
console.log(solaDoldur(">> ", "ts")); // >> tstypeof ile daraltma
JavaScript'in typeof operatörü şu metinlerden birini döndürür: "string", "number", "bigint", "boolean", "symbol", "undefined", "object" ve "function". TypeScript bu değerlerle yapılan karşılaştırmaları type guard olarak tanır. Dikkat edilecek nokta, typeof null değerinin "object" olmasıdır; derleyici bu tarihî tuhaflığı bilir ve sizi uyarır:
function hepsiniYaz(x: string | string[] | null) {
if (typeof x === "object") {
for (const s of x) {
console.log(s);
}
}
}
// TS18047: 'x' is possibly 'null'.typeof x === "object" dalında tip string[] | null olarak kalır. null'ı ayrıca elemeniz gerekir; bunun iki yolunu aşağıda görüyoruz.
Truthiness (doğruluk) ile daraltma
if, &&, || ve ! koşulu önce boolean'a çevirir. 0, NaN, boş string, 0n, null ve undefined yanlış (falsy) sayılır. TypeScript bu kontrolle null ve undefined'ı eler:
function hepsiniYaz(x: string | string[] | null) {
if (x && typeof x === "object") {
console.log(x.join(","));
} else if (typeof x === "string") {
console.log("metin:", x);
} else {
console.log("boş");
}
}
hepsiniYaz(["a", "b"]); // a,b
hepsiniYaz("c"); // metin: c
hepsiniYaz(""); // metin:
hepsiniYaz(null); // boşEşitlik ile daraltma
===, !==, ==, != ve switch da tip daraltır. İki değişken eşitse tipleri de ortak olmalıdır; aşağıda tek ortak tip string olduğu için iki değişken de o dalda string olur. != null ise hem null'ı hem undefined'ı eler:
function karsilastir(x: string | number, y: string | boolean) {
if (x === y) {
return x.toUpperCase() + y.toLowerCase(); // ikisi de string
}
return "eşit değil";
}
function carp(deger: number | null | undefined, kat: number) {
if (deger != null) {
return deger * kat; // deger: number
}
return 0;
}
console.log(karsilastir("ab", "ab")); // ABab
console.log(carp(undefined, 3), carp(4, 3)); // 0 12in operatörü ile daraltma

"ozellik" in nesne kontrolü, union'ın üyelerinden o özelliğe sahip olanları doğru dala, sahip olmayanları yanlış dala ayırır. İsteğe bağlı bir özelliği olan tip ise iki dalda da kalır:
type Balik = { yuz: () => string };
type Kus = { uc: () => string };
type Insan = { yuz?: () => string; uc?: () => string };
function hareket(h: Balik | Kus) {
if ("yuz" in h) {
return h.yuz(); // h: Balik
}
return h.uc(); // h: Kus
}
function hareket2(h: Balik | Kus | Insan) {
if ("yuz" in h) {
h; // h: Balik | Insan
} else {
h; // h: Kus | Insan
}
}
console.log(hareket({ uc: () => "uçuyor" })); // uçuyorTypeScript 4.9 ile in daha da kullanışlı hâle geldi: Hiçbir üyede listelenmeyen bir özelliği kontrol ettiğinizde derleyici nesnenin tipini o özelliği içerecek şekilde genişletir. Bu sayede unknown bir değeri adım adım güvenle inceleyebilirsiniz:
function paketAdi(veri: unknown): string | undefined {
if (veri && typeof veri === "object" && "name" in veri && typeof veri.name === "string") {
return veri.name;
}
return undefined;
}
console.log(paketAdi({ name: "keydal-api", version: "1.0.0" })); // keydal-api
console.log(paketAdi(42)); // undefinedinstanceof ile daraltma
x instanceof Sinif, Sinif.prototype değerinin x'in prototip zincirinde olup olmadığına bakar. TypeScript bu kontrolü de type guard olarak kullanır; new ile oluşturulan değerlerde ve hata nesnelerinde çok işe yarar:
function yaz(x: Date | string) {
if (x instanceof Date) {
return x.toISOString().slice(0, 10); // x: Date
}
return x.toUpperCase(); // x: string
}
console.log(yaz(new Date(Date.UTC(2026, 10, 5)))); // 2026-11-05
console.log(yaz("tarih yok")); // TARIH YOKAtamalar ve bildirilen tip
Bir değişkene değer atadığınızda derleyici o andan sonra değişkenin tipini atanan değere göre daraltır. Ancak sonraki atamalar her zaman değişkenin ilk bildirilen tipine göre denetlenir:
let x = Math.random() < 0.5 ? 10 : "merhaba"; // bildirilen tip: string | number
x = 1; // şimdi x: number
x = "hoşça kal"; // geçerli, bildirilen tipte string var
x = true;
// TS2322: Type 'boolean' is not assignable to type 'string | number'.Type predicate: kendi type guard fonksiyonunuz
Hazır kontroller yetmediğinde dönüş tipi parametre is Tip olan bir fonksiyon yazarsınız. Fonksiyon true döndürdüğünde derleyici argümanı o tipe, false döndürdüğünde kalan tiplere daraltır. Bu fonksiyonlar dizi filter metoduyla da çalışır:
type Balik = { ad: string; yuz: () => void };
type Kus = { ad: string; uc: () => void };
function balikMi(h: Balik | Kus): h is Balik {
return (h as Balik).yuz !== undefined;
}
const hayvanlar: (Balik | Kus)[] = [
{ ad: "Nemo", yuz() {} },
{ ad: "Maviş", uc() {} },
];
const baliklar: Balik[] = hayvanlar.filter(balikMi);
console.log(baliklar.map((b) => b.ad)); // [ 'Nemo' ]TypeScript 5.5'ten itibaren derleyici bazı fonksiyonlar için predicate'i kendisi çıkarır. Sürüm notlarındaki koşullar şunlardır: Fonksiyonun açık bir dönüş tipi olmamalı, tek bir return ifadesi bulunmalı, parametresini değiştirmemeli ve parametreyle ilgili bir daraltmaya bağlı boolean döndürmelidir. Bu sayede aşağıdaki kod artık açıklama gerektirmeden derlenir:
const degerler = [1, undefined, 3];
const sayilar = degerler.filter((d) => d !== undefined); // number[]
console.log(sayilar.map((n) => n * 2)); // [ 2, 6 ]Assertion function: asserts ile daraltma
TypeScript 3.7 ile gelen assertion signature'lar, koşul sağlanmazsa hata fırlatan fonksiyonları modeller. İki biçimi vardır: asserts kosul, fonksiyon normal dönerse koşulun doğru olduğunu söyler; asserts deger is Tip ise argümanın o tipte olduğunu söyler. Fonksiyon çağrıldıktan sonraki tüm kodda daraltma geçerli olur:
function dogrula(kosul: unknown, mesaj: string): asserts kosul {
if (!kosul) throw new Error(mesaj);
}
function metinOlmali(d: unknown): asserts d is string {
if (typeof d !== "string") throw new Error("metin değil");
}
function bagir(girdi: unknown) {
metinOlmali(girdi);
return girdi.toUpperCase(); // girdi: string
}
function yasKontrol(yas: number | null) {
dogrula(yas !== null, "yaş yok");
return yas + 1; // yas: number
}
console.log(bagir("selam"), yasKontrol(41)); // SELAM 42
try {
bagir(5);
} catch (e) {
console.log((e as Error).message); // metin değil
}Assertion fonksiyonlarının bir kısıtı vardır: Çağrılan adın açık bir tip açıklamasıyla bildirilmiş olması gerekir. Tip açıklaması olmayan bir const'a atanmış arrow function ile denediğinizde derleyici hata verir:
const metinMi = (d: unknown): asserts d is string => {
if (typeof d !== "string") throw new Error("metin değil");
};
function kullan(x: unknown) {
metinMi(x);
}
// TS2775: Assertions require every name in the call target to be declared with an explicit type annotation.Çözüm, sabite açık bir tip vermek (const metinMi: (d: unknown) => asserts d is string = ...) ya da fonksiyonu function bildirimiyle yazmaktır.
never ile kapsamlılık kontrolü
Daraltma bir union'daki tüm seçenekleri elediğinde geriye kalan tip never'dır. never her tipe atanabilir, ama never dışında hiçbir tip ona atanamaz. Bu kural, switch'in tüm durumları kapsadığını derleyiciye kontrol ettirmenin yoludur. Union'a yeni bir üye eklenip switch güncellenmezse default dalındaki atama hata verir ve mesajda eksik tipin adı görünür:
interface Daire { kind: "daire"; r: number }
interface Kare { kind: "kare"; a: number }
interface Ucgen { kind: "ucgen"; a: number }
type Sekil = Daire | Kare | Ucgen;
function alan(s: Sekil) {
switch (s.kind) {
case "daire":
return Math.PI * s.r ** 2;
case "kare":
return s.a ** 2;
default:
const _kontrol: never = s;
return _kontrol;
}
}
// TS2322: Type 'Ucgen' is not assignable to type 'never'.case "ucgen" eklendiğinde hata kaybolur. Aynı işi tekrar kullanılabilir bir function eksikDurum(x: never): never yardımcısıyla da yapabilirsiniz; eski handbook bu yöntemi önerir. never tipinin diğer kullanımları için any, unknown, never ve void yazısına bakın.
Teknikleri bir arada görmek

| Teknik | Örnek | Ne zaman |
|---|---|---|
| typeof | typeof x === "string" | Primitive tipler ve fonksiyonlar |
| Truthiness | if (x) | null ve undefined elemek (boş string ve 0 dikkat) |
| Eşitlik | x !== null, x != null | Belirli değerleri ya da null/undefined elemek |
| in | "yuz" in h | Özellik varlığına göre nesne tiplerini ayırmak |
| instanceof | x instanceof Date | Sınıf örnekleri, Error nesneleri |
| Ayırt edici alan | s.kind === "daire" | Discriminated union |
| Type predicate | h is Balik | Tekrar kullanılan özel kontroller, filter |
| Assertion | asserts d is string | Koşul sağlanmazsa hata fırlatan doğrulamalar |
| never | const k: never = s | Tüm durumların ele alındığını kanıtlamak |
Sık yapılan hatalar
typeof x === "object"ile null'ı elediğini sanmak:nullda"object"döndürür.- Truthiness ile boş string ve 0'ı kaybetmek: Sayı ve metin parametrelerinde
!= nullçoğu zaman daha doğrudur. - Daraltmayı tip assertion ile atlamak:
asderleyiciyi susturur ama hiçbir şeyi kontrol etmez; ayrıntısı type assertion yazısında. - Assertion function'ı açık tipsiz bir arrow ile yazmak: TS2775 alırsınız.
- Daraltılmış tipi kalıcı sanmak: Atamayla daralan bir değişkene sonradan bildirilen tipteki başka bir değer atanabilir; atamalar her zaman ilk bildirilen tipe göre denetlenir.
Sık Sorulan Sorular
Type guard ile type predicate aynı şey mi?
Type guard, daraltmaya yol açan her kontrolün genel adıdır (typeof, instanceof gibi). Type predicate ise x is T dönüş tipiyle kendi type guard'ınızı yazmanızı sağlayan sözdizimidir.
Predicate mi assertion function mı kullanmalıyım?
Kontrolün sonucuna göre farklı dallarda farklı işler yapacaksanız predicate (if ile kullanılır). Koşul sağlanmadığında devam etmenin anlamı yoksa ve hata fırlatmak istiyorsanız assertion function daha kısa kod verir.
unknown bir değeri nasıl güvenle kullanırım?
typeof, instanceof, in ve kendi predicate'lerinizle adım adım daraltarak. Bu yaklaşım unknown tipinin varlık sebebidir.
Daraltma çalışma zamanında ek kod üretir mi?
Hayır. Kontrolleri zaten siz JavaScript olarak yazıyorsunuz; TypeScript yalnızca bu kontrolleri okuyup tipleri hesaplar. Yalnızca x is T ve asserts gibi tip açıklamaları çıktıdan silinir.
Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.
İlgili içerikler: TypeScript öğrenme rehberi · Union ve intersection tipleri · any, unknown, never ve void · null, undefined ve strictNullChecks · Type assertion (as) · JavaScript tip dönüşümü · TypeScript ileri seviye yazısı