TypeScript'te strict bayrağı, "strict ailesi" denen bir grup katı tip denetimini tek seferde açar: noImplicitAny, strictNullChecks, strictFunctionTypes, strictBindCallApply, strictPropertyInitialization, noImplicitThis, useUnknownInCatchVariables, alwaysStrict ve strictBuiltinIteratorReturn. TypeScript 6.0 ile strict artık varsayılan olarak açık.

Bu yazıda her bayrağın neyi yakaladığını TypeScript 6.0 derleyicisinden alınmış gerçek hata mesajlarıyla gösteriyor, mevcut bir projeyi strict moda geçirirken izleyebileceğiniz yolu anlatıyoruz. Bayrağın yapılandırma dosyasındaki yeri için tsconfig.json rehberi yazısına bakabilirsiniz.

strict ne yapar?

Resmî tanıma göre strict, program doğruluğu konusunda daha güçlü garantiler veren geniş bir tip denetimi davranışını açar. Bu, ailedeki bütün seçenekleri tek tek açmakla eşdeğerdir; ardından istediğiniz kontrolü ayrıca kapatabilirsiniz. Belgeler önemli bir uyarı da ekler: gelecekteki TypeScript sürümleri bu bayrağın altına yeni ve daha katı kontroller ekleyebilir, dolayısıyla sürüm yükseltmesi yeni tip hataları getirebilir. Örneğin strictBuiltinIteratorReturn bu aileye TypeScript 5.6 ile katıldı.

json
{
  "compilerOptions": {
    "strict": true,
    "strictPropertyInitialization": false
  }
}

Yukarıdaki örnekte ailedeki her şey açık, yalnızca sınıf alanı başlatma kontrolü kapalı. TypeScript 6.0'da strict yazmasanız da açıktır; eski davranışı istiyorsanız açıkça "strict": false yazmanız gerekir.

Ailedeki bayraklar ve yakaladıkları

Ailedeki bayraklar ve yakaladıkları: noImplicitAny, strictNullChecks, strictFunctionTypes, strictBindCallApply
BayrakYakaladığı sorunÖrnek hata kodu
noImplicitAnyTipi çıkarılamayan ve sessizce any olan değerlerTS7006
strictNullChecksnull veya undefined olabilecek değerin kontrolsüz kullanımıTS18048
strictFunctionTypesFonksiyon parametrelerinin güvensiz atanmasıTS2322
strictBindCallApplycall, bind, apply ile yanlış argümanTS2345
strictPropertyInitializationConstructor'da değer verilmeyen sınıf alanlarıTS2564
noImplicitThisTipi any olarak kalan thisTS2683
useUnknownInCatchVariablescatch değişkeninin any yerine unknown olmasıTS18046
alwaysStrictDosyaları JavaScript strict mode ile ayrıştırır-
strictBuiltinIteratorReturnYerleşik iterator dönüş değerinin any olmasıTS18048

noImplicitAny

TypeScript bir değerin tipini çıkaramadığında any'ye düşer ve o değer için denetim yapmaz. Bu bayrak, böyle her durumu hataya çevirir. Aşağıda subtr yazım hatası (doğrusu substring) bayrak kapalıyken fark edilmez:

typescript
function kisalt(metin) {
  // TS7006: Parameter 'metin' implicitly has an 'any' type.
  return metin.subtr(0, 3);
}
kisalt(42);

strictNullChecks

Bu bayrak kapalıyken null ve undefined her tipe atanabilir ve dil onları adeta görmezden gelir. Açıkken kendi tipleri olur ve somut bir değer beklenen yerde kullanılamazlar. Dizinin find metodu sonucu bulamayabilir; bunu hesaba katmazsanız:

typescript
const kullanicilar = [
  { ad: "Elif", yas: 28 },
  { ad: "Mert", yas: 35 },
];

const bulunan = kullanicilar.find((k) => k.ad === "Can");
console.log(bulunan.yas);
// TS18048: 'bulunan' is possibly 'undefined'.

Düzeltmek için değeri kontrol edersiniz; derleyici kontrolden sonra tipi daraltır:

typescript
if (bulunan) {
  console.log(bulunan.yas);
}
console.log(bulunan?.yas ?? "kullanıcı yok"); // kullanıcı yok

Bu konunun ayrıntıları null, undefined ve strictNullChecks ile narrowing ve type guard yazılarında.

strictFunctionTypes

Fonksiyon parametrelerinin daha doğru denetlenmesini sağlar. Yalnızca string kabul eden bir fonksiyonu, string | number alabilecek bir fonksiyon tipine atamak güvensizdir; çünkü daha sonra sayıyla çağrılabilir:

typescript
function selamla(ad: string) {
  console.log("Merhaba, " + ad.toLowerCase());
}

type MetinVeyaSayi = (deger: string | number) => void;

let isleyici: MetinVeyaSayi = selamla;
// TS2322: Type '(ad: string) => void' is not assignable to type 'MetinVeyaSayi'.
//   Types of parameters 'ad' and 'deger' are incompatible.
//     Type 'string | number' is not assignable to type 'string'.

Belgelerin belirttiği bir sınır var: bu kontrol yalnızca fonksiyon sözdizimiyle yazılmış tiplere uygulanır, metot sözdizimiyle (func(x: string): void) yazılanlara uygulanmaz. DOM dahil birçok mevcut sınıf hiyerarşisi bu yüzden etkilenmez.

strictBindCallApply

typescript
function cevir(x: string) {
  return parseInt(x);
}

const a = cevir.call(undefined, "10");   // a: number
const b = cevir.call(undefined, false);
// TS2345: Argument of type 'boolean' is not assignable to parameter of type 'string'.

Bayrak kapalıyken call, bind ve apply her argümanı kabul eder ve sonuç any olur.

strictPropertyInitialization

typescript
class Hesap {
  ad: string;
  tur = "standart";
  eposta: string;
  // TS2564: Property 'eposta' has no initializer and is not definitely assigned in the constructor.
  adres: string | undefined;

  constructor(ad: string) {
    this.ad = ad;
  }
}

ad constructor'da, tur tanımda değer alıyor. adres tipinde undefined olduğu için atanması gerekmiyor. Yalnızca eposta hata veriyor. Bu kontrol strictNullChecks açıkken anlamlıdır. Sınıflarla ilgili diğer konular sınıflar ve erişim belirleyiciler yazısında.

noImplicitThis

typescript
class Dikdortgen {
  constructor(public en: number, public boy: number) {}

  alanFonksiyonu() {
    return function () {
      return this.en * this.boy;
      // TS2683: 'this' implicitly has type 'any' because it does not have a type annotation.
    };
  }
}

İçteki sıradan fonksiyonun this değeri sınıf örneği değildir. Arrow function kullanmak bu sorunu çözer, çünkü arrow function this'i çevresinden alır; bkz. JavaScript this.

useUnknownInCatchVariables

JavaScript'te throw ile her değer fırlatılabilir; yakalanan şeyin bir Error olduğunun garantisi yoktur. Bu bayrak catch değişkenini any yerine unknown yapar:

typescript
try {
  JSON.parse("{bozuk");
} catch (hata) {
  console.log(hata.message);
  // TS18046: 'hata' is of type 'unknown'.
}
typescript
try {
  JSON.parse("{bozuk");
} catch (hata) {
  if (hata instanceof Error) {
    console.log(hata.name); // SyntaxError
  }
}

alwaysStrict ve strictBuiltinIteratorReturn

alwaysStrict, dosyaların ECMAScript strict mode ile ayrıştırılmasını ve çıktıya "use strict" eklenmesini sağlar. TypeScript 6.0 bütün kodun strict mode'da olduğunu varsayar ve alwaysStrict: false yazmak kullanımdan kaldırıldı; denememizde bu ayar TS5107 hatası verdi. await, static, private veya public gibi ayrılmış kelimeleri değişken adı olarak kullanan eski kodların yeniden adlandırılması gerekir.

strictBuiltinIteratorReturn ise Map, Set ve dizilerin yerleşik iteratorlarının dönüş tipini any yerine undefined yapar. Böylece done kontrol edilmeden kullanılan value yakalanır:

typescript
const harita = new Map([["a", 1]]);
const sonuc = harita.keys().next();
console.log(sonuc.value.toUpperCase());
// TS18048: 'sonuc.value' is possibly 'undefined'.

strict ailesinde olmayan katı ayarlar

Bazı faydalı kontroller strict ile açılmaz; ayrıca yazmanız gerekir. En önemlisi noUncheckedIndexedAccess: dizi elemanlarına ve index signature ile tanımlı alanlara erişimde tipe undefined ekler. Aşağıdaki kod yalnızca strict ile hatasız derlendi ama Node 24'te çalışırken çöktü:

typescript
const etiketler: string[] = ["ts", "js"];
const ilk = etiketler[5];
console.log(ilk.toUpperCase());
// strict ile: hata yok, çalışınca TypeError: Cannot read properties of undefined
// noUncheckedIndexedAccess ile: TS18048: 'ilk' is possibly 'undefined'.

exactOptionalPropertyTypes, noImplicitReturns, noImplicitOverride ve noFallthroughCasesInSwitch da bu grupta. tsc --init şablonu bunlardan noUncheckedIndexedAccess ve exactOptionalPropertyTypes ayarlarını varsayılan olarak açar. Index erişimiyle ilgili ayrıntı index signature ve Record yazısında.

Mevcut projeyi strict moda geçirme

Mevcut projeyi strict moda geçirme: Önce durumu görün, noImplicitAny ile başlayın, strictNullChecks'i ayrı bir adımda açın, Kalanları toplu açın

Resmî geçiş rehberi, kod tabanını önce TypeScript'e taşıyıp ardından katı kontrolleri kademeli olarak açmayı önerir. Pratikte işe yarayan sıra şöyledir:

  • Önce durumu görün: TypeScript 6.0'a geçtiğinizde strict kendiliğinden açılır. Hata sayısı çok yüksekse geçici olarak "strict": false yazın ve bayrakları tek tek açın.
  • noImplicitAny ile başlayın: Tipsiz parametreler ve değişkenler görünür hale gelir; diğer kontrollerin işe yaraması için tip bilgisi gerekir.
  • strictNullChecks'i ayrı bir adımda açın: Genellikle en çok hatayı bu üretir. Belgeler, bağımlılıklarınızın da bu moda uygun güncellenmesi gerekebileceğini hatırlatır.
  • Kalanları toplu açın: strictFunctionTypes, strictBindCallApply, noImplicitThis ve useUnknownInCatchVariables genellikle daha az değişiklik ister.
  • Hatayı susturmak yerine düzeltin: ! (non-null assertion) ve as kısa yoldur ama tip güvencesini kaldırır; bkz. type assertion.
  • Sonunda strict: true yazın: Tek tek açtığınız bayrakları silip yalnızca strict bırakın; böylece gelecekteki strict kontrolleri de otomatik devreye girer.

Büyük bir JavaScript kod tabanını taşıyorsanız adımların tamamı JavaScript projesini TypeScript'e geçirme yazısında. Sık karşılaşılan hata kodlarının anlamları için sık TypeScript hataları yazısına bakın.

Sık yapılan hatalar

  • TypeScript 6.0'a geçince hataların nereden geldiğini anlamamak: strict varsayılanı değişti; eski projede strict yazılı değilse artık açık.
  • Bayrağı kapatıp unutmak: "strict": false geçici bir çözüm olmalı. Tek tek kontrolleri açmak için bir plan yapın.
  • Her null hatasını ! ile geçiştirmek: Derleyici susar, çalışma zamanı hatası kalır.
  • strict'in her şeyi kapsadığını sanmak: noUncheckedIndexedAccess gibi önemli kontroller ailenin dışındadır.

Sık Sorulan Sorular

Yeni projede strict kullanmalı mıyım?

Evet. Resmî belgeler yeni kod tabanlarında katı kontrollerin her zaman açılmasını önerir ve TypeScript 6.0 bunu varsayılan yaptı. Başta biraz daha fazla tip yazdırır ama hataları ve editör desteğini belirgin biçimde iyileştirir.

strict açıkken tek bir kontrolü kapatabilir miyim?

Evet. "strict": true ile birlikte, örneğin "strictPropertyInitialization": false yazarsanız ailedeki diğer kontroller açık kalır, yalnızca o kapanır.

Yeni TypeScript sürümü neden yeni hatalar getirdi?

strict bayrağı ileride yeni kontroller kazanabilir; belgeler bunu açıkça söyler. Böyle bir durumda genellikle o kontrol için ayrı bir bayrak da eklenir, isterseniz onu kapatıp kodunuzu sonra düzeltebilirsiniz.

alwaysStrict kapalıyken kodum çalışmıyor, ne yapmalıyım?

TypeScript 6.0 bütün dosyaların strict mode'da olduğunu varsayar. Ayrılmış kelimeleri değişken adı olarak kullanan veya sloppy mode'daki this davranışına dayanan kodu güncellemeniz gerekir.

Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.

İlgili içerikler: TypeScript öğrenme rehberi · tsconfig.json rehberi · strictNullChecks · any, unknown ve never · JavaScript strict mode