2026-08-11dil-ve-araclar3 dk

TypeScript'te tip güvenliği nerede biter

any kullanmamak tip güvenliği demek değil. Derleyicinin size yalan söylediği yerler ve sınırı gerçekten kapatmanın yolu.

TypeScript ile çalışan ekiplerde yaygın bir yanılgı var: any kullanmıyorsak tip güvendeyiz. Oysa TypeScript'in tip denetimi yalnızca derleme zamanında çalışıyor ve çalışma zamanında hiçbir garantisi yok.

Bu, derleyicinin size sessizce yalan söyleyebileceği bir dizi sınır anlamına geliyor. Sınırların hepsi bilinen ve kapatılabilir — ama kapatılması gerektiğini bilmek gerekiyor.

Sınır 1: Sistemin dışından gelen her şey

Bu en büyüğü. Ağdan gelen bir yanıtı bir tiple işaretlediğinizde, TypeScript bunu doğrulamaz; sadece kabul eder.

type Kullanici = { id: number; ad: string };

const yanit = await fetch("/api/kullanici");
const kullanici: Kullanici = await yanit.json(); // ← burada hiçbir kontrol yok

Sunucu ad alanını göndermezse, kullanici.ad çalışma zamanında undefined olur ama derleyici bunu string sanmaya devam eder. Hata, o değeri kullandığınız yerde — genelde tamamen başka bir dosyada — patlar.

Aynı durum şunların hepsi için geçerli: JSON.parse, localStorage, ortam değişkenleri, URL parametreleri, form verisi, veritabanı sürücüsünün döndürdüğü ham satırlar, üçüncü taraf kütüphanelerin tip tanımları.

Çözüm: Sınırda çalışma zamanı doğrulaması. Zod, Valibot, ArkType gibi kütüphaneler bir şemadan hem doğrulayıcı hem TypeScript tipi üretiyor:

const KullaniciSemasi = z.object({ id: z.number(), ad: z.string() });
type Kullanici = z.infer<typeof KullaniciSemasi>;

const kullanici = KullaniciSemasi.parse(await yanit.json());
// buradan sonrası gerçekten güvenli

Kural: Doğrulama, sisteme giriş noktasında bir kez yapılır; içeride bir daha yapılmaz. İçeride tekrar tekrar kontrol eden kod, sınırın kapatılmadığının işaretidir.

Sınır 2: Tip zorlaması (as)

as bir dönüştürme değil, bir emirdir: "bu değeri şu tip say." Derleyici uyar.

const eleman = document.querySelector(".dugme") as HTMLButtonElement;
// eleman yoksa null'dur, ama derleyici artık öyle düşünmüyor

as kullanımlarının çoğu aslında any'nin kibar hâli. Kabul edilebilir olduğu durumlar dar: test verisi, gerçekten dışarıdan garanti edilen bir durum, ya da tip sisteminin ifade edemediği bir daralma. Bunların dışında as gördüğünüzde, altında doğrulanmamış bir varsayım var demektir.

Sınır 3: Dizi ve nesne erişimi

Varsayılan ayarlarla:

const liste: string[] = [];
const ilk = liste[0];  // tipi string — ama değeri undefined
ilk.toUpperCase();     // çalışma zamanı hatası, derleme temiz

Bunu düzelten ayar noUncheckedIndexedAccess. Açıldığında liste[0] tipi string | undefined olur ve derleyici sizi kontrole zorlar. Çoğu projede varsayılan olarak kapalı; açmak mevcut kodda çok sayıda hata gösterir — ki bu, o hataların zaten orada olduğu anlamına gelir.

tsconfig.json tarafında en azından şunlar açık olmalı:

{
  "strict": true,
  "noUncheckedIndexedAccess": true,
  "exactOptionalPropertyTypes": true
}

Sınır 4: Yapısal tipleme aynı şekilli şeyleri karıştırır

TypeScript tipleri isme göre değil şekle göre karşılaştırır. KullaniciId ve SiparisId ikisi de number ise, birbirinin yerine geçebilir ve derleyici itiraz etmez.

function siparisGetir(siparisId: number) { ... }
siparisGetir(kullanici.id); // derleyici mutlu, sistem yanlış

Çözüm, markalı tipler (branded types):

type SiparisId = number & { readonly __marka: "SiparisId" };

Ekstra bir çalışma zamanı maliyeti yok, ve bu hata sınıfını tamamen ortadan kaldırıyor. Kimlik türlerinin karıştığı sistemlerde — çok kiracılı uygulamalarda özellikle — değerli.

Sınır 5: Object.keys ve benzerleri yalan söyler

const nesne = { a: 1, b: 2 };
Object.keys(nesne); // tipi string[], "a" | "b" değil

Bu kasıtlı bir tasarım kararı: nesnede tip tanımında olmayan ek alanlar olabilir. Yani TypeScript burada aslında dürüst davranıyor — ama çoğu geliştirici tersini bekliyor ve döngü içinde tip hatası alıyor.

Pratik kontrol listesi

  1. strict: true ve noUncheckedIndexedAccess: true.
  2. Sisteme giren her veri, giriş noktasında bir şemayla doğrulanıyor.
  3. as kullanımları sayılabilir kadar az ve her biri gerekçeli.
  4. Kimlik tipleri markalı.
  5. Üçüncü taraf tip tanımlarına, kendi kodunuz kadar güvenmiyorsunuz.

Bunların hiçbiri TypeScript'i "gerçekten tip güvenli" yapmıyor — dilin çalışma zamanı hâlâ JavaScript. Ama yaptığı şey daha faydalı: hataların ortaya çıktığı yeri, kullanıldığı noktadan sisteme girdiği noktaya taşıyor. Bir hatanın nerede ortaya çıktığı, hata ayıklama süresinin neredeyse tamamını belirliyor.