TypeScript Strict Mode: Neden ve Nasıl Kullanmalı

TypeScript Strict Mode: Neden ve Nasıl Kullanmalı
TypeScript'in strict mode'u, tip güvenliğini en üst seviyeye çıkaran bir yapılandırma seçeneğidir. Yeni projelerde varsayılan olarak etkinleştirilmesi önerilir, mevcut projelerde ise kademeli geçiş mümkündür. Bu yazıda strict mode'un her alt seçeneğini, faydalarını ve geçiş stratejilerini inceleyeceğiz.
Strict Mode Nedir?
strict: true ayarı, aşağıdaki tüm kontrolleri aynı anda etkinleştirir:
// tsconfig.json
{
"compilerOptions": {
"strict": true
// Bu tek satır aşağıdakilerin hepsini açar:
// "noImplicitAny": true
// "strictNullChecks": true
// "strictFunctionTypes": true
// "strictBindCallApply": true
// "strictPropertyInitialization": true
// "noImplicitThis": true
// "useUnknownInCatchVariables": true
// "alwaysStrict": true
}
}
noImplicitAny
Tip çıkarımı yapılamayan değişkenlerin otomatik any tipini almasını engeller:
// noImplicitAny: false (varsayılan)
function topla(a, b) { // a ve b otomatik any
return a + b;
}
// noImplicitAny: true
function topla(a: number, b: number): number { // Tip belirtmek zorunlu
return a + b;
}
// Yaygın noImplicitAny hataları ve çözümleri
// HATA: Parameter 'event' implicitly has an 'any' type
document.addEventListener("click", (event) => { // event: MouseEvent
console.log(event.target);
});
// Array callback'lerinde genellikle tip çıkarımı çalışır
const sayilar = [1, 2, 3];
const ikiKati = sayilar.map((n) => n * 2); // n: number (otomatik)
strictNullChecks
En etkili strict seçeneklerden biridir. null ve undefined'ı ayrı tipler olarak ele alır:
// strictNullChecks: false
function kullaniciGetir(id: number): Kullanici {
// null döndürebilir ama TypeScript uyarmaz
return null as any;
}
const kullanici = kullaniciGetir(1);
console.log(kullanici.isim); // Runtime hatası!
// strictNullChecks: true
function kullaniciGetir(id: number): Kullanici | null {
if (id === 0) return null;
return { id, isim: "Tarik" };
}
const kullanici = kullaniciGetir(1);
// console.log(kullanici.isim); // HATA: Object is possibly null
// Güvenli erişim yöntemleri
if (kullanici) {
console.log(kullanici.isim); // Güvenli
}
console.log(kullanici?.isim); // Optional chaining
console.log(kullanici?.isim ?? "Bilinmiyor"); // Nullish coalescing
// Array.find ile dikkatli olun
const sayilar = [1, 2, 3, 4, 5];
const bulunan = sayilar.find(n => n > 3);
// bulunan: number | undefined
if (bulunan !== undefined) {
console.log(bulunan * 2); // Güvenli
}
strictNullChecks, TypeScript'in en değerli strict seçeneğidir. Tek başına bile etkinleştirmeye değer. "Null reference" hatalarının büyük çoğunluğunu derleme zamanında yakalar.
strictPropertyInitialization
// Class özelliklerinin constructor'da initialize edilmesini zorunlu kılar
class KullaniciServisi {
// HATA: Property 'apiUrl' has no initializer
// private apiUrl: string;
// Çözüm 1: Constructor'da atama
private apiUrl: string;
constructor(apiUrl: string) {
this.apiUrl = apiUrl;
}
// Çözüm 2: Varsayılan değer
private timeout: number = 5000;
// Çözüm 3: Definite assignment assertion (!)
private db!: Database; // "Sonra atanacak" garantisi
// Çözüm 4: Opsiyonel tanımlama
private cache?: Map<string, any>;
async baslat(): Promise<void> {
this.db = await Database.connect();
this.cache = new Map();
}
}
useUnknownInCatchVariables
// useUnknownInCatchVariables: false (eski davranış)
try {
riskliBirIslem();
} catch (error) {
// error: any - güvensiz!
console.log(error.message); // Runtime'da hata olabilir
}
// useUnknownInCatchVariables: true (TypeScript 4.4+)
try {
riskliBirIslem();
} catch (error) {
// error: unknown - güvenli!
if (error instanceof Error) {
console.log(error.message); // Güvenli
} else if (typeof error === "string") {
console.log(error);
} else {
console.log("Bilinmeyen hata:", error);
}
}
// Yardımcı fonksiyon
function hataMesajiGetir(error: unknown): string {
if (error instanceof Error) return error.message;
if (typeof error === "string") return error;
return "Bilinmeyen hata oluştu";
}
catch bloğunda error parametresinin tipini any olarak belirtmek, useUnknownInCatchVariables ayarını devre dışı bırakır. Bu alışkanlıktan kaçının: catch (error: any) yerine catch (error) kullanın ve tip daraltma yapın.
Kademeli Strict Geçiş Stratejisi
// Adım 1: Başlangıç - sadece temel kontroller
{
"compilerOptions": {
"strict": false,
"noImplicitAny": false,
"strictNullChecks": false
}
}
// Adım 2: noImplicitAny'yi aç
{
"compilerOptions": {
"strict": false,
"noImplicitAny": true
}
}
// Adım 3: strictNullChecks'i aç (en zor adım)
{
"compilerOptions": {
"strict": false,
"noImplicitAny": true,
"strictNullChecks": true
}
}
// Adım 4: Tam strict mode
{
"compilerOptions": {
"strict": true
}
}
// Bonus: Ek katı kontroller
{
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"exactOptionalPropertyTypes": true
}
}
Strict Mode ile Yaygın Pattern'ler
// Non-null assertion yerine güvenli alternatifler
// Kaçının:
const element = document.getElementById("app")!;
// Tercih edin:
const element = document.getElementById("app");
if (!element) {
throw new Error("App elementi bulunamadı");
}
element.innerHTML = "Merhaba";
// Optional chaining ile güvenli erişim
interface Kullanici {
isim: string;
adres?: {
sehir: string;
ilce?: string;
};
}
function sehirGetir(kullanici: Kullanici): string {
return kullanici.adres?.sehir ?? "Belirtilmemiş";
}
// Discriminated union ile tip güvenliği
type Sonuc<T> =
| { ok: true; deger: T }
| { ok: false; hata: string };
function guvenliParse(json: string): Sonuc<unknown> {
try {
return { ok: true, deger: JSON.parse(json) };
} catch {
return { ok: false, hata: "Geçersiz JSON" };
}
}
alwaysStrict seçeneği, JavaScript "use strict"'i otomatik olarak ekler.
Sonuç
Strict mode, TypeScript'in sunduğu tip güvenliğinden tam olarak yararlanmanın anahtarıdır. Yeni projelerde strict: true ile başlamak en iyi pratiktir. Mevcut projelerde kademeli geçiş stratejisiyle her seçeneği ayrı ayrı etkinleştirin. Strict mode'un getirdiği ekstra tip kontrolü, kısa vadede daha fazla kod yazmanızı gerektirse de, uzun vadede çok daha az hata ile karşılaşmanızı sağlar.