JavaScript dinamik olarak yazılmıştır; bu gerçekten kullanışlıdır — hızlı yineleyebilir, özgürce prototip oluşturabilir
ve bir derleme adımı olmadan yayınlayabilirsiniz. Ancak bu esnekliğin bir bedeli vardır: bir hata sınıfının tamamı
yalnızca çalışma zamanında ortaya çıkar. Bir fonksiyon string bekler, undefined alır ve uygulamanız
gece 2'de prodüksiyonda patlar. TypeScript,
JavaScript'in üzerine tam olarak bu hataları derleme zamanında, düzenleyicinizde, herhangi bir şey yayınlanmadan önce yakalayan
bir statik tür sistemi ekler. Bu makale bunun pratikte ne anlama geldiğini açıklar — gerçek kod,
dürüst ödünleşimler ve abartı yok.
TypeScript Gerçekte Nedir
TypeScript, JavaScript'in bir üst kümesidir: her geçerli .js dosyası aynı zamanda geçerli
.ts'dir. Bir dosyayı yeniden adlandırabilir, sıfır tür ek açıklaması ekleyebilirsiniz ve düzgün derlenir. TypeScript'in
eklediği şeyler — tür ek açıklamaları, arayüzler, genericler, enumlar — derleme zamanında tamamen kaldırılır. Çıktı
saf JavaScript'tir. TypeScript neyin çalıştığını değiştirmez; çalıştırılmadan önce bilebileceklerinizi
değiştirir.
Derleyici tsc'dir ve
npm aracılığıyla kurulur. Onu
.ts dosyalarınıza yönlendirirsiniz ve çalışma zamanınızın (Node.js, bir tarayıcı, Deno) çalıştırabileceği
.js dosyaları üretir. TypeScript'e özgü hiçbir sözdizimi üretime hiçbir zaman ulaşmaz — türler yalnızca
geliştirici ve araç zinciri için vardır.
GitHub'daki TypeScript deposu
kendisi büyük bir TypeScript projesidir ve bu size nasıl ölçeklendiğine dair bir fikir verir.
# Compile a single file
npx tsc src/index.ts
# Compile a whole project (uses tsconfig.json)
npx tsc
# Watch mode — recompile on every save
npx tsc --watchTemel Fayda: Çalışma Zamanından Önce Hatalar
İşte TypeScript'in en görünür şekilde çözdüğü sorun. Bir alanın string veya null olabileceği
bir API yanıtıyla çalıştığınızı hayal edin. Saf JavaScript'te bu, üretime kadar sessizce başarısız olur:
// JavaScript — no error until this actually runs with a null value
function formatDisplayName(user) {
return user.displayName.toUpperCase(); // 💥 TypeError if displayName is null
}
// This looks fine in isolation. The bug only appears when a user
// has no display name set — which might be rare, but it will happen.
const name = formatDisplayName({ displayName: null });TypeScript bunu kod çalıştırılmadan önce yakalar:
interface User {
id: number;
displayName: string | null;
email: string;
}
function formatDisplayName(user: User): string {
return user.displayName.toUpperCase();
// ❌ TypeScript error: Object is possibly 'null'.
// Property 'toUpperCase' does not exist on type 'null'.
}
// Fix: handle the null case explicitly
function formatDisplayName(user: User): string {
if (user.displayName === null) {
return user.email; // fall back to email
}
return user.displayName.toUpperCase(); // TypeScript now knows this is safe
}Bu çoğu geliştirici için "aha" anıdır. Hata mesajı size tam olarak neyin yanlış olduğunu
ve nerede olduğunu söyler — düzenleyicinizde, tek bir satır çalıştırmadan önce. strict modu etkinleştirildiğinde, TypeScript
strict modda varsayılan olarak açık olan
strictNullChecks
özelliği aracılığıyla null ve undefined sorunlarını yakalamada özellikle agresiftir.
tsc'den gelen bir hata, kodunuzun bir tür tutarsızlığına sahip olduğu anlamına gelir — TypeScript çalıştırmadan
başarısız olacağını (veya olabileceğini) kanıtlayabilir. Tür hatasını düzeltin ve hata sınıfını tamamen ortadan kaldırmış olursunuz.TypeScript'in Tür Sistemine Genel Bakış
Her şeyi açıklama eklemeniz gerekmez. TypeScript atamalardan, dönüş değerlerinden ve fonksiyon çağrılarından türleri çıkarır — çoğu zaman sadece normal JavaScript yazarsınız ve ücretsiz olarak tür denetimi alırsınız. Ancak çıkarım yeterli olmadığında açıklama sözdizimini bilmek yardımcı olur.
// Primitives
const productName: string = 'Wireless Keyboard';
const price: number = 79.99;
const inStock: boolean = true;
// TypeScript infers these without annotations — same effect
const productName = 'Wireless Keyboard'; // inferred: string
const price = 79.99; // inferred: number
// Arrays
const tags: string[] = ['electronics', 'peripherals'];
const ratings: number[] = [4.5, 4.8, 4.2];
// Objects with interfaces
interface Product {
id: number;
name: string;
price: number;
category: string;
inStock: boolean;
description: string | null; // union type — string or null
}
// Union types — a value that could be one of several types
type Status = 'active' | 'inactive' | 'pending'; // string literal union
type ID = string | number; // string or number
// Function with typed parameters and return type
function formatProductCard(product: Product): string {
const stockLabel = product.inStock ? 'In Stock' : 'Out of Stock';
const desc = product.description ?? 'No description available';
return `${product.name} — $${product.price.toFixed(2)} (${stockLabel})
${desc}`;
}
// Generic function — works with any type, preserves it
function firstOrDefault<T>(items: T[], fallback: T): T {
return items.length > 0 ? items[0] : fallback;
}
const first = firstOrDefault(['a', 'b', 'c'], 'z'); // inferred: string
const num = firstOrDefault([1, 2, 3], 0); // inferred: numberTypeScript el kitabı tür sistemi üzerinde derinlemesine gider — gerçekten iyi yazılmıştır ve temellere hakim olduğunuzda okunmaya değerdir.
Bir Projede TypeScript Kurulumu
TypeScript'i bir projeye eklemek yaklaşık beş dakika sürer. Derleyiciyi bir geliştirme bağımlılığı olarak kurarsınız,
bir yapılandırma dosyası oluşturursunuz ve .js dosyalarını mantıklı olan hızda .ts olarak yeniden adlandırmaya başlarsınız.
# Install TypeScript as a dev dependency
npm install -D typescript
# Generate tsconfig.json with sensible defaults
npx tsc --initOluşturulan tsconfig.json'un çoğu yorumlanmış onlarca seçeneği vardır. Bilmeniz
gereken temel olanlar:
{
"compilerOptions": {
"target": "ES2020", // what JavaScript version to output
"module": "commonjs", // module system (commonjs for Node, ESNext for bundlers)
"outDir": "./dist", // where compiled .js files go
"rootDir": "./src", // where your .ts source files live
"strict": true, // enables all strict type checks — highly recommended
"esModuleInterop": true, // smoother interop with CommonJS modules
"skipLibCheck": true // skip type checks on .d.ts files in node_modules
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}Yeni bir projede her zaman strict: true'yu etkinleştirin. strictNullChecks,
noImplicitAny ve strictFunctionTypes dahil olmak üzere çeşitli kontrolleri bir araya getirir.
Mevcut bir kod tabanında bunları kademeli olarak etkinleştirmeniz gerekebilir —
ancak greenfield için her şeyin başlangıcında strict olun.
TypeScript vs JavaScript — Gerçek Ödünleşimler
TypeScript'in birçok gerçek avantajı vardır, ancak gerçek maliyetleri de vardır. İşte dürüst bir değerlendirme:
- Gerçekten çalışan otomatik tamamlama. Düzenleyiciniz her nesnenin şeklini bilir, bu nedenle tahmin etmek yerine doğru özellik adlarını ve yöntem imzalarını önerebilir. Bu tek başına her gün zaman kazandırır.
- Prodüksiyona ulaşmadan önce yakalanan hatalar. Null dereferences, yanlış argüman türleri, eksik gerekli özellikler — TypeScript bunları yazma zamanında, gece 3'te bir olay kanalında değil işaretler.
- Daha güvenli refactoring. Bir arabirimde bir alanı yeniden adlandırın ve TypeScript hemen güncellenmesi gereken her çağrı sitesini işaretler. Büyük bir JavaScript kod tabanında bu tür bir değişiklik korkutucudur.
- Kod kendini belgeler.
sendEmail(to: string, subject: string, body: string, options?: EmailOptions): Promise<SendResult>gibi bir fonksiyon imzası uygulamayı okumadan ihtiyacınız olan her şeyi söyler. - Takımlar için daha iyi. Birden fazla geliştirici bir kod tabanını paylaştığında, türler modüller arasında bir sözleşme oluşturur. Kodunuzu refactor edebilirsiniz ve meslektaşınızınkini bozmadan.
Ve dürüst maliyetler:
- Bir derleme adımı ekler. Küçük bir script veya hızlı bir prototip için, test etmeden önce
tscçalıştırmak gerçek bir sürtüşmedir. Vanilla JavaScript anında çalışır. - İlk kurulum zaman alır.
tsconfig.json'ı yapılandırmak, üçüncü taraf kütüphaneler için tür tanımlamaları eklemek (@types/express, vb.) ve düzenleyicinizi doğru şekilde yapılandırmak birkaç saatlik iştir. anyher şeyi baltalıyor. TypeScript'in bir kaçış yolu vardır — herhangi bir şeyianyolarak yazabilirsiniz, bu da o değer için tür denetimini devre dışı bırakır.any'nin aşırı kullanımı, güvenlik olmadan TypeScript'in sürtüşmesini almanız anlamına gelir. Bu bir koltuk değneği, çözüm değil.- Üçüncü taraf kütüphane türleri geride kalabilir. Her npm paketi TypeScript tanımları içermez.
Bazıları eksik veya güncel olmayan topluluk tarafından sürdürülen
@types/*paketlerine dayanır.
TypeScript'nin Gerçekten Parladığı Yerler
TypeScript en büyük getiriyi üç durumda sağlar: büyük kod tabanları, paylaşılan kütüphaneler ve zaman içinde refactor edilecek her şey. Tür sistemi, yorumlar veya README dosyalarının aksine her zaman güncel olan canlı belgeler olarak işlev görür.
Pratik bir örnek: uygulamanız kullanıcı verisi döndüren bir REST API çağırıyor. TypeScript olmadan, API'nin beklediğinizi döndüreceğine güveniyorsunuz. TypeScript ile yanıtı modeller ve bir şey eşleşmediğinde anında geri bildirim alırsınız:
interface ApiUser {
id: number;
username: string;
email: string;
avatarUrl: string | null;
createdAt: string; // ISO 8601 date string
role: 'admin' | 'editor' | 'viewer';
}
interface ApiResponse<T> {
data: T;
total: number;
page: number;
perPage: number;
}
async function fetchUsers(page: number): Promise<ApiResponse<ApiUser[]>> {
const response = await fetch(`/api/users?page=${page}`);
if (!response.ok) {
throw new Error(`Failed to fetch users: ${response.status}`);
}
return response.json() as Promise<ApiResponse<ApiUser[]>>;
}
// Now every consumer of this function knows exactly what they'll get
const result = await fetchUsers(1);
result.data.forEach(user => {
// TypeScript knows user.role is 'admin' | 'editor' | 'viewer'
// It will error if you try to access a property that doesn't exist
console.log(`${user.username} (${user.role})`);
});Tür denetimini geçici olarak devre dışı bırakmanız gerektiğinde, any yerine unknown
kullanın. Fark şu: any tüm kontrolleri sessizce atlar, unknown ise değeri kullanmadan önce
türü daraltmanızı zorunlu kılar — güvenliği tamamen kaybetmeden kaçış yolunu alırsınız.
// ❌ any — TypeScript trusts you completely, no checks
function processData(data: any) {
data.nonExistentMethod(); // no error — TypeScript looks away
}
// ✅ unknown — you have to prove what it is before using it
function processData(data: unknown) {
if (typeof data === 'string') {
console.log(data.toUpperCase()); // safe — TypeScript knows it's a string here
} else if (Array.isArray(data)) {
console.log(data.length); // safe — TypeScript knows it's an array
}
}TypeScript Playground, bu desenlerle deneme yapmanın en hızlı yoludur. Kodu yapıştırın, derlenmiş JavaScript çıktısını ve tür hatalarını gerçek zamanlı olarak görün — kurulum gerekmez.
Sonuç
TypeScript sihir değildir ve her proje için doğru değildir. Ancak büyüyen, birden fazla kişi tarafından sürdürülen veya refactor edilecek herhangi bir JavaScript kod tabanı için — geliştirme deneyimini gerçekten değiştirir. Tür sistemi, çalışma zamanı hatalarının tüm bir kategorisini yayınlanmadan önce yakalar, otomatik tamamlamayı gerçekten kullanışlı hale getirir ve refactoring'i riskli bir manuel süreçten araç zincirinin hallettiği bir şeye dönüştürür.
Başlamak için resmi TypeScript belgelerine bakın — iyi yapılandırılmış ve başlangıç dostudur. TypeScript Playground herhangi bir kurulum olmadan deneme yapmak için harikadır. MDN TypeScript sözlük girişi ikinci bir perspektif istiyorsanız sağlam bir tek sayfalık genel bakıştır. TypeScript'te JSON verileriyle çalışıyorsanız, bu sitedeki JSON to TypeScript aracı, herhangi bir JSON yükünden doğrudan TypeScript arayüzleri üretir — bir API yanıtını hızlıca modellemek istediğinizde kullanışlıdır.