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:
strictnoUncheckedIndexedAccessexactOptionalPropertyTypes
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ı
- Sürümü sabitleyin.
package.jsoniçinde TypeScript sürümünü^5gibi bir aralık yerine, test ettiğiniz belirli bir sürüme kilitleyin. Derleyici davranışı alt sürümler arasında değişebilir. tsconfigtabanını sıkılaştırın. Yukarıdakistrictailesini açın. Mevcut kod tabanında kademeli geçiş yapacaksanız, dizin bazlı ayrıtsconfigdosyaları kullanabilirsiniz.- Sınır katmanlarını belirleyin. Ağ, dosya sistemi ve kullanıcı girdisi gibi dış dünyayla temas eden noktaları işaretleyin. Bu noktalarda
unknownile başlayıp doğrulama sonrası tipli veri üretin. satisfiesveconsttip 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.- Kaynak yönetimini
usingile sadeleştirin. Runtime desteğini doğruladıktan sonra,try/finallybloklarının yerini alabilir. - Ayrımcı birlikleri standart hâle getirin. API yanıtları, hata durumları ve UI durumları için ortak bir
status/kindalanı belirleyin.
Yaygın Hatalar
asile tip zorlamak.as, çalışma zamanı doğrulaması yapmaz. Doğrulanmamış veriyiasile tipli göstermek, güvenlik açıklarının tip sistemine sızmasına yol açar.anyile hızlı çözüm. Kısa vadede derleyiciyi susturur, uzun vadede tip güvenliğini ortadan kaldırır.unknownve daraltma tercih edilmelidir.strictkapalıyken yeni özellikleri kullanmak.satisfiesveya ayrımcı birlikler,strictkapalıyken beklenen faydayı vermez.usingözelliğini runtime desteğini kontrol etmeden kullanmak. Hedef ortamSymbol.disposedesteklemiyorsa, 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.