TypeScript nedir, neyi çözmeye çalışır?
TypeScript, JavaScript üzerine kurulu, JavaScript ile birlikte çalışan ve JavaScript’e dönüştürülen bir programlama dilidir. Temel katkısı, program çalışmadan önce kodun bazı hatalı kullanımlarını yakalayabilen bir tip denetleyicisi ve editör araçları sağlamasıdır. Tarayıcıya TypeScript gönderilmez; dağıtım hedefi hâlâ JavaScript’tir. Bu ayrım önemlidir: TypeScript çalışma zamanını kendiliğinden güvenli kılmaz, dış servisin gönderdiği JSON’u doğrulamaz ve hatalı mimariyi otomatik düzeltmez. Geliştiricinin niyetini daha görünür hâle getirir, değişikliklerin etkisini analiz etmeyi kolaylaştırır ve editörde daha iyi geri bildirim verir.
“En iyi dil” ihtiyaca göre değişir. Zaten React, Node.js veya başka bir JavaScript altyapısı kullanan bir ekipte TypeScript, mevcut paket ve geliştirici bilgisini koruyarak ölçeklenebilirliği artırır. Küçük bir tek kullanımlık betikte başlangıç maliyeti gereksiz olabilir. Yoğun sayısal hesapta Python veya Rust daha uygun olabilir. Seçim yaparken ekip deneyimi, çalıştırma ortamı, kütüphane uyumu, dağıtım biçimi ve bakım süresini birlikte değerlendirin; yalnızca bir benchmark sıralamasına göre karar vermeyin.
Tipler derleme sırasında silindiği için tip açıklamalarını güvenlik duvarı gibi görmek yanlıştır. Örneğin `type User = { id: string }` bildirimi, internetteki bir isteğin gerçekten `id` gönderdiğini kanıtlamaz. Dış dünyadan gelen veriyi ayrıştırmak, yetkilendirmek ve doğrulamak çalışma zamanında yapılır. TypeScript bu doğrulama kodunun tutarlı kullanılmasını sağlar; doğrulama kütüphanesinin veya uygulama kontrolünün yerini tutmaz.
Sağlam bir başlangıç: küçük, sıkı ve anlaşılır yapılandırma
Yeni projede önce çalışma zamanını ve araç zincirini belirleyin: tarayıcı mı, Node.js mi, yoksa ikisi birden mi? ESM modüllerini kullanıyorsanız TypeScript `module` ve `moduleResolution` ayarlarını seçtiğiniz çalıştırıcı, paketleyici veya çalışma zamanının beklentileriyle eşleştirin. Tarayıcıya ve Node’a aynı modül ayarını kopyalamak her zaman doğru değildir. TypeScript Handbook’un modül rehberi, derleyicinin modül biçimini, çözümlemeyi ve hedef JavaScript sürümünü neden birlikte düşündüğünü açıklar.
Bir başlangıç `tsconfig.json` örneği aşağıdadır. Bu ayarlar sihirli bir reçete değildir: kullandığınız Vite, tsx, ts-node, bundler veya Node sürümünün resmi kılavuzuyla karşılaştırın. `strict` açık olduğunda eksik tip bilgisi daha erken görünür; `noEmit` kullanımı JavaScript üretimini ayrı bir araç yapıyorsa mantıklıdır. `target` ve modül ayarları gerçek dağıtım ortamını yansıtmalıdır. Bir ayarı yalnızca derleyici uyarı vermesin diye kapatmadan önce uyarının hangi varsayımı sorguladığını anlayın.
Kurulumdan sonra her geliştiricinin aynı komutları çalıştırması için paket betikleri ekleyin: `typecheck`, `test` ve `build`. CI bu komutları çalıştırır, başarısızsa değişikliği bloklar. Tiplere ek olarak biçimlendirme ve lint kuralları, kod incelemesinde tekrarlanan biçim tartışmalarını azaltır. Ancak yüzlerce kural içeren bir yapılandırma başlangıçta ürüne değer katmıyorsa bakım maliyetidir. Önce ekibin gerçek sorunlarına karşılık gelen kısa bir kural seti belirleyip zaman içinde genişletin.
Daraltma ve ayırt edilebilir birleşimler: durumları güvenli modellemek
Web uygulamalarında sık karşılaşılan hata, birbirinden farklı durumları gevşek bir nesneye veya bir dizi isteğe bağlı alana sıkıştırmaktır. Bir yükleme kartı örneğinde `loading`, `error`, `data` ve `empty` durumları birbiriyle çelişen biçimde aynı anda taşınabilir. Ayırt edilebilir birleşim, her geçerli durumu ayrı bir nesne şekliyle tarif eder; sabit `kind` alanı sayesinde `switch` içinde TypeScript ilgili özellikleri daraltır. Böylece “yükleniyor” iken başarı mesajına erişmeye çalışmak gibi yanlış yolları daha kolay yakalarsınız.
Bilinmeyen dış veriyi doğrudan bu tipe çevirmeyin. Önce `unknown` olarak alın ve doğrulayın. Bir API’nin JSON yanıtını sunucu sözleşmesi, istemci tipi ve çalışma zamanı doğrulaması üçlüsüyle düşünün. Üretimde bu üçü zamanla ayrışabilir: sunucu alanı yeniden adlandırabilir, eski istemci bir süre daha yaşayabilir veya beklenmedik `null` gelebilir. Sürümleme, geriye uyumluluk ve açık hata mesajları veri modelinin parçasıdır.
Birleşim tasarımında gereksiz tip hilesi yerine basit alanlar kullanın. `never` ile exhaustive kontrol, bir duruma yeni varyant eklendiğinde yakalanmayan `switch` dalını bulabilir. Tip sistemi uygulama mantığınızın tüm olasılıkları ele almasına yardım eder; ama iş kuralının doğru olup olmadığını yalnızca alan adlarından çıkaramaz. Kritik kararı testlerle ve ürün gereksinimiyle doğrulayın.
01type Result<T> =02 | { kind: 'loading' }03 | { kind: 'success'; data: T }04 | { kind: 'error'; message: string };05 06function describe<T>(result: Result<T>): string {07 switch (result.kind) {08 case 'loading': return 'Yükleniyor';09 case 'success': return 'Hazır';10 case 'error': return result.message;11 default: {12 const exhaustive: never = result;13 return exhaustive;14 }15 }16}API sınırı: tip açıklaması değil, gerçek doğrulama
Form girdisi, URL parametresi, dosya, veritabanı kaydı ve HTTP yanıtı uygulamanın dış sınırlarıdır. Bu noktalarda verinin hangi şekle sahip olduğunu varsaymak yerine kontrol edin. Hafif uygulamada elle yazılmış küçük bir doğrulayıcı yeterli olabilir; karmaşık şemalar ve paylaşılan istemci/sunucu sözleşmeleri için Zod, Valibot veya Ajv gibi araçları değerlendirebilirsiniz. Bunların her biri ek paket, öğrenme maliyeti ve çalıştırma maliyeti getirir; seçimi ekip standardı, JSON Schema ihtiyacı ve paket hedefi belirlesin.
Doğrulama yalnızca “tip doğru mu?” sorusuyla bitmez. Sayısal bir alanın güvenli aralıkta olması, metnin uzunluk sınırı, kullanıcının bu kaynağa erişme yetkisi ve istek oranı da kontrol edilmelidir. İstemci tarafındaki kontroller kullanıcı deneyimi içindir; yetkilendirme sunucu tarafında yapılmalıdır. Konsola tüm hassas payload’u yazmak hata ayıklamayı kolaylaştırabilir ama kişisel veri sızdırabilir. Kayıtları en az gerekli veriyle tutun ve erişimi sınırlandırın.
Bir doğrulama katmanını tek bir yerde tutmak, farklı ekranların aynı endpoint’i farklı kurallarla yorumlamasını önler. Hatanın hangi alanda ve neden oluştuğunu kullanıcıya güvenli, anlaşılır bir dille sunun; iç altyapı ayrıntılarını veya sırları sızdırmayın. İyi API tasarımında beklenebilir hata bir `Result` veya HTTP durum kodu ile ifade edilir. Bir istisnayı sessizce yutup boş nesne döndürmek çoğunlukla hatayı daha sonra ve daha pahalı biçimde ortaya çıkarır.
API sürümü değişirken eski istemciyi bir anda bozmayın. Bir alanı kaldırmadan önce kullanımını ölçün, eski adı bir süre uyum katmanıyla destekleyin ve değişikliği sürüm notuna ekleyin. OpenAPI şeması veya paylaşılan bir contract dosyası ekipler arasındaki anlaşmayı görünür kılar; yine de şemayla uygulama kodunun ayrışmadığını CI’da doğrulamak gerekir. Uçtan uca sözleşme testi, “tipler derlendi” ile “servislerin gerçekten aynı JSON’u konuşuyor” arasındaki boşluğu kapatır. Geriye dönük uyumluluk özellikle mobil uygulama ve önbellekte kalmış istemcilerde önemlidir.
Tipler niyeti açıklar; dış dünyadan gelen verinin doğru olduğunu çalışma zamanı kontrolleri kanıtlar.
Asenkron işlerde hata, iptal ve yarış koşulları
JavaScript’in `Promise` ve `async/await` modeli, I/O bekleyen kodu okunabilir biçimde ifade eder. TypeScript dönüş tipi ve hata yollarını açıklamaya yardımcı olur; ancak iki isteğin hangi sırayla tamamlanacağını garanti etmez. Arama kutusu için eski sorgunun yavaş yanıtı, yeni sorgudan sonra gelirse ekranda eski sonuçlar görünebilir. `AbortController` ile artık gerekli olmayan HTTP isteğini iptal etmek, sonuçları sıra numarasıyla filtrelemek veya istekleri debounce etmek bu ürün davranışını ele alır.
Promise hatalarını yakalarken hata tipini `unknown` olarak ele alıp güvenli biçimde daraltın. JavaScript’te her tür değer fırlatılabildiğinden, yakalanan şeyin `Error` olduğunu baştan varsaymak doğru değildir. Bir hatayı kullanıcıya göstermeden önce teknik log ile kullanıcı mesajını ayırın. Ağ hatası, geçersiz yanıt, oturum süresinin dolması ve erişim reddi aynı toparlanma adımına sahip olmayabilir.
Performans sorununu tahminle çözmeyin. Büyük bir istemci demeti, gereksiz state güncellemeleri veya pahalı render işlemleri gerçek kullanıcı deneyimini etkileyebilir. Üretim derlemesini ölçün, kaynak haritasıyla büyük bağımlılıkları bulun, gerçek cihaz ve yavaş ağ koşullarını test edin. Tip sisteminin derleme çıktısına maliyeti sıfıra yakındır ama eklenen doğrulama ve kütüphaneler çalışma süresine katılır. Bu ikisini aynı “TypeScript yavaş mı?” sorusuna indirgemeyin.
Test stratejisi: tip kontrolü tek başına test değildir
Derleyicinin doğruladığı özelliklerle testlerin doğruladığı davranış farklıdır. Tip denetimi yanlış argüman ve eksik birleşim kolu gibi programlama hatalarını bulabilir; fiyatın doğru yuvarlanıp yuvarlanmadığını veya kullanıcının siparişini gerçekten kaydettiğini bilemez. Saf iş kuralları için birim test, modül sınırları için entegrasyon testi ve kritik uçtan uca akışlar için tarayıcı testi kullanın. Her testin ürün açısından hangi riski azalttığını açıklayabilmek, test piramidini somutlaştırır.
TypeScript’te tiplerin derleme zamanında bulunması, JavaScript test koşucusunun dosyayı doğrudan çalıştıracağı anlamına gelmez. Vite, tsx, ts-node veya seçtiğiniz koşucunun TypeScript desteğini ve modül biçimini dokümantasyonundan kontrol edin. CI’da önce bağımlılıkları deterministik kurun, ardından biçim/lint, tip kontrolü, test ve üretim derlemesi çalıştırın. Yerel makinede geçen fakat CI’da başarısız olan adımlar, sürüm ve ortam farklarını gösterebilir.
Sınır değerleri özellikle test edin: boş liste, sıfır, negatif değer, çok uzun metin, geçersiz UTF-8, zaman aşımı, tekrar gönderilen istek ve eşzamanlı güncelleme. Hata yolunu hiç çalıştırmayan bir test kümesi başarıyı ispatlamaz. Sabit saat ve rastgelelik, bağımlılık enjeksiyonu veya sahte servislerle kontrol altına alınabilir; gerçek veritabanı ve ağ davranışını doğrulayan testler ise ayrı bir entegrasyon katmanında tutulabilir. Kapsama yüzdesi bir sinyaldir, kalite sertifikası değildir.
Erişilebilir arayüz ve bakım yapılabilir bileşenler
TypeScript ile bir butonun `onClick` alanını doğru tiplemek, butonun klavyeyle kullanılabilir veya erişilebilir olduğunu garanti etmez. Anlamsal HTML (`button`, `label`, `nav`, `main`), görünür klavye odağı, doğru ad ve hata mesajları ayrıca tasarlanmalıdır. Bileşen API’lerini gerçek kullanım senaryolarına göre modelleyin: her görsel ayrıntı için boolean prop eklemek yerine varyantları anlamlı adlandırın. Gereksiz genel bileşen, takım arkadaşının kullanmasını zorlaştırabilir.
Kullanıcı arayüzünde durumları modelleyin: başlangıç, yüklenme, boş sonuç, başarılı sonuç, hata ve iptal. Aynı asenkron kaynağı birçok bileşende ayrı ayrı yönetmek tutarsız geri bildirim oluşturur. Sunucu durumuyla geçici form durumunu birbirinden ayırın. Durum yönetimi kütüphanesini ancak gerçek gereksinim (önbellek, yeniden doğrulama, paylaşılmış state, zaman yolculuğu gibi) ortaya çıktığında ekleyin; en popüler paketi otomatik eklemek mimari karar değildir.
Tip adlarını ve dosya yapısını ürün diline yakın tutun. Her alan için `IUser` gibi tekrarlanan önekler yerine dilin doğal kalıplarını izleyin; fonksiyonun niyetini belli eden isimleri tercih edin. `any` kaçış kapısıdır: veri `unknown` ile tutulup daraltılabiliyorsa bilinmeyen bilgiyi korur ve her kullanımda karar vermeyi gerektirir. Büyük JavaScript kod tabanını dönüştürürken her dosyayı tek seferde çevirmek şart değildir. Sınırlar, testler ve `allowJs` gibi geçiş seçenekleriyle riski küçük, gözlemlenebilir parçalara bölün.
Örnek gerçek proje: Türkçe portfolyo için içerik API’si
Örnek bir portfolyo/ajans sitesinde ziyaretçi blog araması yapar, yazıları kategoriye göre süzer ve iletişim formu gönderir. TypeScript burada birden fazla yerde değer üretir: kart ve ayrıntı sayfalarının ortak yazı modelini kurar, dil seçimini sınırlı bir `tr | en` birleşimi olarak tanımlar, filtre durumunu açık biçimde belirtir ve servis sınırında beklenmedik JSON’u görünür kılar. Astro veya benzeri statik bir çatı, içeriği build sırasında üretirken küçük istemci betikleri arama/filtre etkileşimini sağlayabilir. Tüm siteyi istemci taraflı uygulama yapmak zorunlu değildir.
Basit uygulama planı: önce içerik modelini ve URL yapısını tasarlayın; sonra örnek yazıyı statik veriyle render edin; arama ve kategoriyi klavyeyle kullanılabilir HTML kontrollerine bağlayın; veri editör tarafından API’den geliyorsa doğrulayın; her dilde canonical ve metadata’yı kontrol edin. Form endpoint’i eklendiğinde sunucu tarafı doğrulama, spam sınırlama ve hata geri bildirimi uygulayın. Özel veriyi istemciye veya loglara gereksiz taşımayın.
Başka uygun proje fikirleri: tarayıcıda çalışan harcama takip paneli, Node.js ile webhook alıcısı, tasarım sistemi bileşen kütüphanesi, çevrimdışı çalışan görev listesi, birden fazla API’yi birleştiren içerik panosu. Başlangıçta “TypeScript kullanıyor” diye veri tabanı, kuyruk veya mikroservis eklemeyin. Önce temel kullanım akışını tamamlayın, hataları görünür kılın ve ölçüm elde edin. Sonra ölçek veya bakım sorunu gerçek olduğunda mimariyi büyütün.
Bir kart örneği kodu yalnızca tipe güvenmek yerine gerçek projede testle eşleştirilmelidir: `formatDate` farklı saat dilimlerinde beklenen çıktıyı vermeli, bilinmeyen kategori güvenli bir varsayılana düşmeli, boş görsel için anlamlı alternatif görünmelidir. Ürün içeriği ve görsellerinin telif/lisansını da takip edin. Başarılı örnek; derlenen kod kadar dağıtımda çalışan, farklı ekranlarda anlaşılır ve sahibi belli olan kod demektir.

Yaygın yanlışlar ve karar kontrol listesi
“Her şeyi tipe dönüştürürsem hata kalmaz” yanılgısı ilk sıradadır. Derleyici iş mantığı, izin politikası, SQL enjeksiyonu, sunucu kullanılabilirliği veya tasarım kullanılabilirliği garantilemez. `as User` ile bir veriye etiketi yapıştırmak da onu doğrulamaz. Tip iddiasını ancak kontrol veya güvenilir üretici bu iddiayı haklı çıkardığında kullanın. `!` non-null assertion ve `any` çok sık görülüyorsa, sınırdaki veri modelini yeniden inceleyin.
İkinci hata, ayarları bağlamdan koparıp kopyalamaktır. Uygulamanın modül biçimi, paketleyicisi, browser desteği ve TypeScript sürümü birbirine bağlıdır. Üçüncü hata, karmaşık generic’leri her yerde kullanmaktır: bir soyutlama tekrar eden iş kuralı veya güvenli API sağlamıyorsa okunabilirliği düşürebilir. Dördüncü hata, hızlı derleme uğruna üretim doğrulamasını unutmak; beşincisi, sadece mutlu yolu test etmektir.
Karar vermeden önce şu soruları ekipçe yanıtlayın: Hangi JavaScript çalıştırma ortamı hedefleniyor? Kullanılan paketlerin tür açıklamaları güvenilir mi? Derleme ve test komutları CI’da aynı mı? HTTP ve kullanıcı girdileri nerede doğrulanıyor? Kod tabanında gevşek tipler nerede yoğunlaşıyor? Kaynak haritası ve hata raporları hangi sorunları gösteriyor? Büyüyen proje için derleme süresi kabul edilebilir mi? Bu cevaplar TypeScript’in nerede katı, nerede esnek kullanılacağını belirler.
Sonuçta TypeScript, JavaScript’ten kaçış yolu değil, büyük ve yaşayan JavaScript programlarını anlaşılır kılmanın araçlarından biridir. Sıkı başlangıç ayarı, küçük ve doğru veri modelleri, dış sınırda çalışma zamanı doğrulaması, anlamlı testler ve anlaşılır hata yönetimi birlikte çalışır. Bu temelleri kurduktan sonra araç seçimi—React, Vue, Svelte, Astro, Node.js, Deno veya başka bir seçenek—ürünün ihtiyaçlarına göre yapılabilir. Dil tercihi başarıyı tek başına belirlemez; ekipteki kararların kalitesi ve sürdürülebilir uygulama belirler.
Resmî kaynaklar ve ileri okuma
Teknik davranışları birincil kaynaklardan kontrol etmek ve konuyu uygulayarak derinleştirmek için:
- TypeScript Handbook: Modules
- TypeScript Handbook: Narrowing
- TypeScript Handbook: Generics
- TypeScript: TypeScript for JavaScript Programmers
- MDN: Fetch API
Kaynaklar ilgili dil, standart kütüphane veya aracın birincil dokümantasyonudur. Sürüme göre değişebilen ayrıntılarda kendi projenizin kullandığı sürümün belgelerini esas alın.