ViraStack
  • Akademi
  • Hakkında
  • Destek
Genel BakışKaynaklarKatkı
ViraStack

Frontend geliştiricileri için DX odaklı araç seti: starter’lar, ajan kuralları, form hook’ları ve rehber.

Ürünler

  • ViraStack Start
  • ViraStack AI
  • ViraStack Mask
  • ViraStack Password
  • ViraStack Guide

Keşfet

  • Akademi
  • Hakkında
  • Marka
  • Destek

© 2026 ViraStack.

Açık kaynak · MIT

TypeScript

04 / 09

Narrowing ve type guard

Union'ı daraltma, discriminated union ve güvenli tip kontrolü.

Narrowing Nedir

Union tipli bir değer birkaç şeyden biri olabilir. TypeScript size yalnızca hepsinde ortak olan işlemlere izin verir:

function formatPrice(price: number | string) {
  return price.toFixed(2);
  // Hata: Property 'toFixed' does not exist on type 'string | number'.
}

Çözüm, değeri bir if ile kontrol etmektir. TypeScript kodun akışını takip eder ve her dalda değerin olabileceği en dar tipi hesaplar. Bildirilen tipten daha dar bir tipe inmeye narrowing (daraltma), bunu sağlayan kontrollere type guard denir.1

function formatPrice(price: number | string) {
  if (typeof price === "string") {
    return price; // price: string
  }
  return price.toFixed(2); // price: number
}

return'den sonra string ihtimali kalmadığı için TypeScript alttaki satırda price'ı number kabul eder. Buna control flow analysis denir.1 Ekstra bir sözdizimi yoktur; yazdığınız sıradan JavaScript kontrolleri tipi daraltır.

Yerleşik Kontroller

KontrolNe zaman
typeof x === "string"Primitive tipleri ayırmak
if (x) / if (!x)null, undefined ve boş değerleri elemek
x === "shipped", x != nullBelirli bir değere ya da null'a göre ayırmak
"weight" in xObject'leri sahip oldukları alana göre ayırmak
x instanceof DateClass örneklerini (Date, Error) ayırmak

typeof'un bir tuzağı var: JavaScript'te typeof null da "object" döner. TypeScript bunu bilir; typeof x === "object" dalında x hâlâ null olabilir ve sizi 'x' is possibly 'null' hatasıyla uyarır.1

Truthiness kontrolü (if (value)) kısa ama dikkat ister: 0 ve "" de falsy'dir.1 Stok gibi 0 olabilen değerlerde açık karşılaştırma yapın:

function showStock(stock: number | undefined) {
  if (stock === undefined) {
    return "Bilgi yok";
  }
  return stock === 0 ? "Tükendi" : `${stock} adet`; // stock: number
}

if (!stock) yazsaydınız stok 0 olduğunda da "Bilgi yok" görünürdü. x != null ise tek seferde hem null hem undefined'ı eler.1

in ile object'leri bir alanın varlığına göre ayırırsınız:1

type PhysicalProduct = { name: string; weight: number };
type DigitalProduct = { name: string; downloadUrl: string };

function shippingLabel(product: PhysicalProduct | DigitalProduct) {
  if ("weight" in product) {
    return `${product.weight} kg`; // PhysicalProduct
  }
  return "İndirme linki e-postayla gönderilir"; // DigitalProduct
}

Discriminated Union

Gerçek projelerde en çok işinize yarayacak kalıp budur. Union'daki her üyeye aynı isimde, literal tipli bir alan verirsiniz (genellikle status, type ya da kind). Bu ortak alana discriminant denir; onu kontrol etmek, union'ı tek bir üyeye daraltır.12

Ürün listesini API'den çeken bir ekranın üç durumu olsun:

type ProductsState =
  | { status: "loading" }
  | { status: "success"; data: Product[] }
  | { status: "error"; message: string };

function renderProducts(state: ProductsState): string {
  switch (state.status) {
    case "loading":
      return "Yükleniyor...";
    case "success":
      return `${state.data.length} ürün bulundu`; // yalnızca burada data var
    case "error":
      return `Hata: ${state.message}`; // yalnızca burada message var
    default: {
      const exhaustiveCheck: never = state;
      return exhaustiveCheck;
    }
  }
}

{ isLoading: boolean; data?: Product[]; error?: string } gibi opsiyonel alanlarla kurulan bir tip, "hem yükleniyor hem hata var" gibi imkansız durumlara izin verir ve her yerde ! kullanmaya iter. Discriminated union bu durumları tip seviyesinde imkansız kılar.1 React'te useReducer action'ları da aynı kalıpla yazılır; bunu React'te tipler dersinde göreceksiniz.

never ile eksiksiz kontrol

default dalındaki satır bir güvenlik ağıdır. Bütün durumlar ele alındıysa geriye hiçbir ihtimal kalmaz, state'in tipi never olur ve atama geçerlidir.1 Union'a ileride { status: "idle" } eklenir ama case "idle": unutulursa TypeScript unutulan durumu adıyla söyler:

const exhaustiveCheck: never = state;
// Hata: Type '{ status: "idle"; }' is not assignable to type 'never'.

Kendi Type Guard'ınız

Kontrol uzun ya da tekrar eden bir hale gelince onu fonksiyona çıkarırsınız. Dönüş tipine value is Product yazarsanız fonksiyon bir type predicate olur: true dönerse TypeScript değeri Product kabul eder.1

function isProduct(value: unknown): value is Product {
  return (
    typeof value === "object" &&
    value !== null &&
    "id" in value &&
    typeof value.id === "number" &&
    "name" in value &&
    typeof value.name === "string" &&
    "price" in value &&
    typeof value.price === "number" &&
    "stock" in value &&
    typeof value.stock === "number"
  );
}

Uyarı

TypeScript, fonksiyonun içindeki kontrolün value is Product iddiasıyla uyuştuğunu doğrulamaz. Kontrolü eksik yazarsanız tip yanlış daraltılır. Kendi type guard'ınız, as kadar dikkat ister.3

TypeScript 5.5'ten beri basit fonksiyonlar için predicate'i kendisi çıkarır (inferred type predicates). En çok filter'da işe yarar:4

const cartProducts = cartIds
  .map((id) => products.find((p) => p.id === id))
  .filter((product) => product !== undefined);
// TS 5.5+: Product[] (öncesinde (Product | undefined)[])

filter((x) => !!x) sayılarda çalışmaz, çünkü false dönmesi hem undefined hem 0 anlamına gelebilir; açık karşılaştırma yazın.4

Assertion fonksiyonları

Type guard boolean döner ve if ister. Assertion fonksiyonu ise koşul sağlanmazsa hata fırlatır; çağrıdan sonraki satırlarda tip daralmış olur. Dönüş tipi asserts value is ... şeklinde yazılır.5

function assertIsDefined<T>(
  value: T,
  message: string,
): asserts value is NonNullable<T> {
  if (value === undefined || value === null) {
    throw new Error(message);
  }
}

function getPrice(id: number) {
  const product = products.find((p) => p.id === id); // Product | undefined
  assertIsDefined(product, `Ürün bulunamadı: ${id}`);
  return product.price; // product: Product
}

<T> ve NonNullable<T> sözdizimini Generic'ler ve Utility types derslerinde göreceksiniz.

as ve ! ile Tipi Zorlamak

Type assertion (as) TypeScript'e "bu değerin tipini ben senden iyi biliyorum" demektir. Hiçbir çalışma zamanı kontrolü yapmaz; yanılıyorsanız hata uygulama çalışırken çıkar.6 Postfix ! (non-null assertion) ise değerin null ya da undefined olmadığını kontrol etmeden iddia eder.6

const data = JSON.parse('{"id": 1}') as Product;
data.name.toUpperCase(); // derlenir, çalışırken patlar: name undefined

const product = products.find((p) => p.id === 99)!;
product.price; // derlenir, ürün yoksa çalışırken patlar

TypeScript yalnızca birbiriyle örtüşen tipler arasında as'e izin verir. "1299" as number gibi ilgisiz bir dönüşüm Conversion of type 'string' to type 'number' may be a mistake... hatası verir.6

Kural basit: önce gerçek bir kontrolle daraltın (if, type guard, discriminated union); as ve !'i hata mesajını susturmak için değil, yalnızca TypeScript'in bilemeyeceği ama sizin kesin bildiğiniz durumlarda kullanın.

unknown'ı Daraltmak

Dış dünyadan gelen veri, tipi bilinmeyen veridir. response.json() ve JSON.parse ise any döner ve kontrolü tamamen kapatır. Değeri unknown olarak alıp daraltmak daha güvenlidir: TypeScript, kontrol etmeden kullanmanıza izin vermez.2

async function fetchProducts(): Promise<Product[]> {
  const response = await fetch("/api/products");
  const data: unknown = await response.json();

  if (!Array.isArray(data) || !data.every(isProduct)) {
    throw new Error("Beklenmeyen ürün verisi");
  }
  return data; // data: Product[]
}

isProduct içindeki "id" in value && typeof value.id === "number" zinciri, TypeScript 4.9 ile mümkün oldu: in kontrolü artık tipte listelenmemiş bir alanı da erişilebilir yapar.7

catch bloğundaki hata da unknown'dır, çünkü JavaScript'te her şey fırlatılabilir. strict modda açık olan useUnknownInCatchVariables bunu sağlar.89

try {
  await addToCart(productId);
} catch (error) {
  console.error(error.message);
  // Hata: 'error' is of type 'unknown'.

  const message = error instanceof Error ? error.message : String(error);
  console.error(message); // güvenli
}

İpucu

Gerçek projelerde API yanıtlarını elle yazılmış type guard'larla değil, Zod gibi bir şema kütüphanesiyle doğrularsınız. Şema hem çalışma zamanında veriyi kontrol eder hem de tipi kendisi üretir.10 Formlar yolundaki Zod dersi bunu ayrıntılı anlatır.

Kendin Dene

  • TS Playground'da ProductsState'e { status: "empty" } ekleyin ve never kontrolünün hangi satırda hata verdiğine bakın.

  • isProduct'tan stock kontrolünü silin. TypeScript hata veriyor mu? Neden vermediğini düşünün.

  • [1, 0, undefined].filter((x) => x !== undefined) ile filter((x) => !!x) sonuçlarının tiplerini fareyle üzerine gelerek karşılaştırın.

Detaylı Öğrenmek İçin

  • Resmi doküman: TypeScript Handbook'un Narrowing sayfası; bu dersteki her kontrolün örnekli anlatımı.1

  • Kitap: Matt Pocock'un çevrimiçi okunabilen Total TypeScript Essentials kitabının "Unions, Literals, and Narrowing" bölümü.2

  • Yazı: Kent C. Dodds'un catch bloğundaki unknown hatadan güvenle mesaj çıkarma yazısı.9

  • Yazı: TypeScript 5.5 duyurusundaki "Inferred Type Predicates" bölümü; özelliği geliştiren Dan Vanderkam yazdı.4

  • Resmi doküman: Zod'un tanıtım sayfası; şema ile çalışma zamanı doğrulaması.10

Kaynaklar

  • 1DokümanTypeScript Handbook: Narrowing

    `typeof`, truthiness, eşitlik, `in`, `instanceof`, type predicate, discriminated union ve `never` ile eksiksiz kontrol.

  • 2MakaleMatt Pocock

    : — Narrowing, `unknown`'ın neden güvenli olduğu ve discriminated union ile durum modelleme.

  • 3MakaleMatt Pocock

    : — Kendi type predicate ve assertion fonksiyonlarınızın `as` kadar riskli olabileceği uyarısı.

  • 4MakaleAnnouncing TypeScript 5.5

    20 Haziran 2024. `filter` ile inferred type predicates, koşulları ve `!!x` sınırlaması.

  • 5DokümanTypeScript 3.7 Release Notes: Assertion Functions

    `asserts condition` ve `asserts val is Type` imzaları.

  • 6DokümanTypeScript Handbook: Everyday Types

    Type assertion ve non-null assertion; çalışma zamanında kontrol yapmadıkları.

  • 7MakaleAnnouncing TypeScript 4.9

    `in` operatörüyle listelenmemiş alanlarda daraltma; `unknown` veriden alan okuma örneği.

  • 8DokümanTypeScript 4.4 Release Notes: useUnknownInCatchVariables

    `catch` değişkeninin `any` yerine `unknown` olması ve bayrağın `strict` ile birlikte açılması.

  • 9MakaleKent C. Dodds

    : — Her şeyin fırlatılabileceği ve `getErrorMessage` yardımcı fonksiyonu.

  • 10DokümanZod

    "TypeScript-first schema validation with static type inference"; şema ile veriyi doğrulama.

Bu sayfayı düzenle

Son güncelleme tarihi: 17 Ekim 2026

Önceki adım03. Interface, type ve unionSonraki adım05. Generic'ler