TypeScript 5.x Yenilikleri ve Güvenli Tip Mimarisi

## TypeScript 5.x'e Genel Bakış TypeScript 5.x serisi, dilin tip sistemini genişletirken derleyici tarafında da önemli değişiklikler getirdi. Bu rehb...

TypeScript 5.x Yenilikleri ve Güvenli Tip Mimarisi

TypeScript 5.x'e Genel Bakış

TypeScript 5.x serisi, dilin tip sistemini genişletirken derleyici tarafında da önemli değişiklikler getirdi. Bu rehber, orta seviye geliştiricilerin günlük iş akışında kullanabileceği yenilikleri ve bu yeniliklerin üzerine kurulabilecek güvenli bir tip mimarisini ele alıyor.

Önkoşullar: Node.js ve npm (veya eşdeğeri) kurulu bir ortam, tsconfig.json ile temel düzeyde çalışabilme, generics ve union tipleri gibi TypeScript kavramlarına aşinalık.

Sürüm kapsamı: Bu rehber TypeScript 5.x hattını konu alır. Belirli bir alt sürüme bağlı kalmadan, 5.x boyunca geçerliliğini koruyan özelliklere ve yaklaşımlara odaklanır. Kullandığınız tam sürümü npx tsc --version ile doğrulayabilirsiniz. Aşağıdaki örneklerin çalıştığını iddia etmiyorum; kendi projenizde deneyerek davranışı doğrulamanız gerekir.

TypeScript 5.x'te Öne Çıkan Dil Özellikleri

const Tip Parametreleri

Fonksiyonlarda ve sınıflarda tip parametrelerini const ile işaretleyebilirsiniz. Bu, çağrı sırasında geçilen değişmez (literal) değerlerin daha dar bir tip olarak çıkarılmasını sağlar.

function firstElement<const T>(arr: readonly T[]): T | undefined {
  return arr[0];
}

const first = firstElement(["a", "b", "c"]);
// first: "a" | "b" | "c" | undefined

const olmadan aynı çağrı string | undefined dönerdi. Bu özellik, sabit listelerden türetilen tiplerde gereksiz genişlemeyi engeller.

satisfies Operatörü

satisfies, bir değerin belirli bir tipe uyduğunu doğrularken değerin kendi çıkarılan tipini korumasını sağlar. as ile karıştırılmamalıdır: as tipi zorlar, satisfies ise uyumu denetler.

type Config = Record<string, string | number>;

const config = {
  host: "localhost",
  port: 8080,
} satisfies Config;

// config.port hâlâ number olarak bilinir, string | number değil.

Bu, özellikle geniş bir kayıt tipine uyan ama alanları tek tek dar kalan nesnelerde işe yarar.

using ve Açık Kaynak Yönetimi

using bildirimi, kapsam dışına çıkıldığında Symbol.dispose (veya asenkron varyantta Symbol.asyncDispose) metodunu çağırarak kaynakları serbest bırakır. Bu, dosya tanıtıcıları, kilitler veya bağlantılar için try/finally kalıbını azaltır.

class TempFile {
  [Symbol.dispose]() {
    // temizlik burada yapılır
  }
}

{
  using file = new TempFile();
  // blok sonunda file[Symbol.dispose]() çağrılır
}

Bu özelliğin çalışması için hedef ortamın ilgili runtime desteğini ve tsconfig ayarlarının uygun olmasını gerektirdiğini unutmayın.

Dekoratörler

TypeScript 5.x, standart ECMAScript dekoratör sözdizimini destekler. Bu, sınıf, metot, erişimci ve alanların üzerine davranış eklemeyi tip güvenli biçimde mümkün kılar. Eski deneysel dekoratörlerle (experimentalDecorators) uyumluluk ayrı bir konudur; projeye başlarken hangi modu kullandığınızı netleştirin.

Güvenli Tip Mimarisi İçin İlkeler

Yeni dil özellikleri, mimarinin yerini tutmaz. Aşağıdaki ilkeler, 5.x özellikleriyle birlikte kullanıldığında tip güvenliğini artırır.

any Yerine unknown ve Doğrulama

Dış kaynaklardan (API yanıtı, JSON.parse, kullanıcı girdisi) gelen veriler unknown olarak alınmalı ve kullanılmadan önce doğrulanmalıdır. any, tip denetimini tamamen devre dışı bırakır; unknown ise kullanım öncesi daraltma zorunluluğu getirir.

function parseUser(input: unknown): { id: number; name: string } {
  if (
    typeof input === "object" &&
    input !== null &&
    "id" in input &&
    "name" in input &&
    typeof (input as { id: unknown }).id === "number" &&
    typeof (input as { name: unknown }).name === "string"
  ) {
    return input as { id: number; name: string };
  }
  throw new Error("Geçersiz kullanıcı verisi");
}

Bu tür doğrulamaları elle yazmak yerine, şema tabanlı doğrulama kütüphaneleriyle birleştirmek daha sürdürülebilir olur. Hangi kütüphaneyi seçerseniz seçin, doğrulamanın çıktısını TypeScript tipine bağlayın; böylece şema ile tip tanımı arasında kopukluk oluşmaz.

Ayrımcı Birlikler (Discriminated Unions)

Durum makinelerini ve API sonuçlarını modellemenin en güvenli yollarından biri ayrımcı birliklerdir. Ortak bir literal alan (örneğin kind veya status) üzerinden daraltma yapılır.

type Result<T> =
  | { status: "ok"; value: T }
  | { status: "error"; message: string };

function handle<T>(r: Result<T>): T | never {
  switch (r.status) {
    case "ok":
      return r.value;
    case "error":
      throw new Error(r.message);
  }
}

switch üzerinde never dönüşü ve tsconfig içindeki strict ayarları birlikte kullanıldığında, yeni bir durum eklendiğinde derleyici eksik kalan dalları yakalar.

strict Ailesini Kapatmayın

tsconfig.json içinde en azından şu ayarların açık olması beklenir:

  • strict
  • noUncheckedIndexedAccess
  • exactOptionalPropertyTypes

noUncheckedIndexedAccess, dizi ve nesne indekslemelerinde undefined olasılığını hesaba katar. exactOptionalPropertyTypes ise undefined atanmış bir alan ile hiç bulunmayan alanı birbirinden ayırır. Bu ayarlar başlangıçta bazı hataları ortaya çıkarır; bu, kodun gerçekte olduğundan daha güvenli görünmesini engellediği için istenen bir durumdur.

Uygulama Adımları

  1. Sürümü sabitleyin. package.json içinde TypeScript sürümünü ^5 gibi bir aralık yerine, test ettiğiniz belirli bir sürüme kilitleyin. Derleyici davranışı alt sürümler arasında değişebilir.
  2. tsconfig tabanını sıkılaştırın. Yukarıdaki strict ailesini açın. Mevcut kod tabanında kademeli geçiş yapacaksanız, dizin bazlı ayrı tsconfig dosyaları kullanabilirsiniz.
  3. Sınır katmanlarını belirleyin. Ağ, dosya sistemi ve kullanıcı girdisi gibi dış dünyayla temas eden noktaları işaretleyin. Bu noktalarda unknown ile başlayıp doğrulama sonrası tipli veri üretin.
  4. satisfies ve const tip parametrelerini yerinde kullanın. Sabit yapılandırma nesneleri ve literal listeler için bu araçlar, tip genişlemesini kontrol altına alır.
  5. Kaynak yönetimini using ile sadeleştirin. Runtime desteğini doğruladıktan sonra, try/finally bloklarının yerini alabilir.
  6. Ayrımcı birlikleri standart hâle getirin. API yanıtları, hata durumları ve UI durumları için ortak bir status/kind alanı belirleyin.

Yaygın Hatalar

  • as ile tip zorlamak. as, çalışma zamanı doğrulaması yapmaz. Doğrulanmamış veriyi as ile tipli göstermek, güvenlik açıklarının tip sistemine sızmasına yol açar.
  • any ile hızlı çözüm. Kısa vadede derleyiciyi susturur, uzun vadede tip güvenliğini ortadan kaldırır. unknown ve daraltma tercih edilmelidir.
  • strict kapalıyken yeni özellikleri kullanmak. satisfies veya ayrımcı birlikler, strict kapalıyken beklenen faydayı vermez.
  • using özelliğini runtime desteğini kontrol etmeden kullanmak. Hedef ortam Symbol.dispose desteklemiyorsa, beklenen temizlik çalışmaz.
  • Dekoratör modunu karıştırmak. Standart ve deneysel dekoratörler aynı projede öngörülemez sonuçlar doğurabilir; proje genelinde tek bir mod seçin.

Güvenlik Etkileri

Tip sistemi bir güvenlik katmanı değildir; ancak yanlış kullanıldığında güvenlik açıklarını gizleyebilir. as ile doğrulanmamış veriyi tipli göstermek, çalışma zamanında beklenmeyen değerlerin iş mantığına ulaşmasına neden olur. Aynı şekilde, strict kapalıyken undefined ve null durumlarının gözden kaçması, kimlik doğrulama veya yetkilendirme kontrollerinde atlamalara yol açabilir. Dış girdinin her zaman unknown olarak alınması ve doğrulanmadan kullanılmaması, bu riskleri azaltır.

Sonuç

TypeScript 5.x, tip sistemini daha ifade gücü yüksek ve daha denetlenebilir hâle getiren araçlar sunuyor. const tip parametreleri, satisfies, using ve standart dekoratörler günlük kodda yerini alabilir. Ancak bu özelliklerin gerçek faydası, strict ayarların açık olduğu ve sınır katmanlarında unknown ile doğrulama yapıldığı bir mimaride ortaya çıkar. Kendi projenizde önce tsconfig tabanını sıkılaştırıp ardından yeni özellikleri kademeli olarak devreye almanız, hem geçiş maliyetini hem de regresyon riskini azaltır.

İLGİLİ İÇERİKLER

Bunları da Okumak İsteyebilirsiniz