Menu

TypeScript Tip Daraltma (Narrowing): Kontrol Akışı Analizi

Daraltma (narrowing), TypeScript'in string | number gibi geniş bir tipi bir if, bir switch içinde ya da erken bir return sonrasında belirli bir tipe dönüştürme şeklidir. Tüm daraltma biçimleri tek yerde: typeof, truthiness, eşitlik, in, instanceof, atamalar, type predicate'ler ve discriminated union'lar.

Bu sayfada çalıştırılabilir editörler var - düzenle, çalıştır ve sonucu anında gör.

Tip daraltma (type narrowing), TypeScript'in kodun daha önce yaptığı kontrollere dayanarak kodun belirli bir noktasında bir değer için daha özel bir tip bulmasıdır. Bir string | number parametresi if (typeof x === "string") içinde string, else içinde number olur.

Kontrolden önce value.toFixed(2) çağırmak bir derleme hatası olurdu, çünkü toFixed metodu string üzerinde yoktur. Kontrol sıradan JavaScript'tir ve çalışma zamanında çalışır; daraltma ise derleyicinin onu okuyup tipi ayarlamasıdır. Fazladan hiçbir şey üretilmez.

Kontrol Akışı Analizi

TypeScript bir fonksiyondaki her yolu izler: if/else, erken return ve throw, switch, döngüler ve kısa devre operatörleri &&, ||, ?? ve ?:. Her noktada bir değişkenin tipi, orada hâlâ mümkün olan şeydir.

Erken return stili ("guard clause'lar") daraltmanın en okunaklı yoludur: önce tuhaf durumları ele alın, fonksiyonun geri kalanı temiz tiple çalışsın.

Daraltmanın Tüm Yolları

BiçimÖrnekDaralttığı
typeoftypeof x === "string"primitive'ler ve fonksiyonlar
Truthinessif (x)null, undefined ve falsy literal'leri çıkarır
Eşitlikx === "a", x == null, x !== undefinedliteral'ler, null, undefined
in"swim" in petözelliğe göre nesne union'ları
instanceoferr instanceof TypeErrorsınıf örnekleri
Array.isArrayArray.isArray(x)diziler ve geri kalan her şey
Atamax = 5atanan tipe
Type predicatefunction isUser(x: unknown): x is Userkontrol edebileceğiniz her şey
Assertion fonksiyonufunction assertUser(x: unknown): asserts x is Userçağrıdan sonraki her şey
Ayırıcı özellikswitch (shape.kind)etiketli union'lar

Son üçü type guard'lar ve discriminated union'lar sayfalarında anlatılıyor. Geri kalanlar aşağıda.

Truthiness ile Daraltma

if (x), null ve undefined tiplerini (ve false, 0, "" literal tiplerini) çıkarır. Kısadır ve klasik bir tuzağı vardır: 0 ve "" falsy'dir, bu yüzden geçerli değerler eksikmiş gibi ele alınır.

Sayılar ve string'ler için açıkça undefined veya null ile karşılaştırın (ya da ?? kullanın). Truthiness, hiçbir zaman falsy olmayan nesneler, diziler ve fonksiyonlar için uygundur.

Eşitlik ile Daraltma

===, !==, == ve != iki tarafı da daraltır. Bir literal ile karşılaştırmak o literal'e daraltır; == null (gevşek eşitlik) tek bir kontrolde hem null hem undefined ile eşleşir ve gevşek eşitliğin alışılmış olduğu tek yerdir.

İki değişkeni karşılaştırmak ikisini de ortak olabilecekleri şeye daraltır: a: string | number ve b: string | boolean değerleri a === b kontrolünden geçerse if içinde ikisi de string olur.

in Operatörü

"key" in obj, nesne tiplerinden oluşan bir union'ı o özelliğe sahip olan (ya da sahip olabilecek) üyelere daraltır.

in, bir nesne olduğunu bildiğiniz anda unknown üzerinde de çalışır: typeof v === "object" && v !== null && "id" in v sonrasında TypeScript, v değerinin unknown tipinde bir id özelliğine sahip olduğunu bilir. Kendi tasarladığınız union'lar için ortak bir etiket özelliği (kind: "fish"), metotları yoklamaktan daha anlaşılırdır: bu kalıba discriminated union denir.

Atama ile Daraltma

Bir değişkenin bildirilmiş bir tipi ve atamalarını izleyen daraltılmış bir tipi vardır. Bir değer atamak, onu bildirilmiş tiple sınırlı olmak üzere o değerin tipine daraltır.

Daraltmanın Kaybolduğu Yerler

Daraltma yereldir ve temkinlidir. Birkaç durum onu sıfırlar:

  • Farklı bir ifade. obj.name kontrolü obj.name (ve obj["name"]) ifadesini daraltır, ama key bir literal değil de bir string değişkeni olduğunda obj[key] ifadesini ve kontrolden önce alınmış bir kopyayı daraltmaz.
  • Callback'ler ve yeniden atama. Bir callback'in içinde, daraltılmış bir let yalnızca callback oluşturulduktan sonra yeniden atanmıyorsa daraltmasını korur. Bir const ya da hiç yeniden atanmayan bir parametre daraltılmış kalır.
  • Yardımcılarda gizlenmiş kontroller. isString(x: unknown): boolean şeklindeki bir fonksiyon derleyiciye hiçbir şey söylemez. Ona x is string şeklinde bir type predicate dönüş tipi verin, çağrıları typeof gibi daraltır.

Derleyici index.ts(5,38): error TS18048: 'x' is possibly 'undefined'. bildirir. Callback daha sonra, x = undefined sonrasında çalışabilir. O son atamayı silin (ya da değeri if içinde bir const değişkenine kopyalayın), kod derlenir ve iki kez 5 yazdırır.

boolean döndüren bir yardımcı, neyi kanıtladığını bildirerek düzeltilebilir. Type guard budur:

function isString(value: unknown): value is string {
  return typeof value === "string";
}

TypeScript 5.5'ten beri derleyici basit arrow function'lar için bu tür predicate'leri çıkarır; list.filter((x) => x !== undefined) ifadesinin artık undefined içermeyen bir dizi döndürmesinin nedeni budur.

Sıkça Sorulan Sorular

TypeScript'te tip daraltma nedir?

Daraltma, TypeScript'in kodun yaptığı bir kontrole dayanarak bir blok içinde bir değişkenin tipini inceltmesidir. if (typeof x === "string") sonrasında bir string | number, if içinde yalnızca string, else içinde yalnızca number olur. Derleyici her noktadaki tipi bulmak için if, else, return, switch, &&, || ve ?: yapılarını izler; buna kontrol akışı analizi denir.

TypeScript tipimi neden daraltmıyor?

Yaygın nedenler: kontrol, kullandığınızdan farklı bir ifade üzerinde yapılmıştır (obj.a kontrol edilmiş, tipi string olan bir key ile obj[key] kullanılmış); değer, bir callback oluşturulduktan sonra yeniden atanan bir let değişkenidir ve callback daraltmayı kaybeder; ya da kontrol, x is T type predicate'i yerine düz boolean döndüren bir yardımcının içinde gizlidir.

Tip daraltma çalışma zamanında çalışır mı?

Kontroller çalışır: typeof, instanceof, in ve === çalışan sıradan JavaScript'tir. Daraltmanın kendisi ise yalnızca derleme zamanındadır. TypeScript çalışma zamanı kontrollerinizi okur ve statik tipleri onlara göre ayarlar; üretilen JavaScript'e hiçbir şey eklenmez.

TypeScript'te bir unknown tip nasıl daraltılır?

Aynı kontrollerle: typeof value === "string", Array.isArray(value), value instanceof Date ya da nesneler için typeof value === "object" && value !== null && "id" in value. Yeniden kullanılabilir kontroller için value is T dönüş tipli bir type guard fonksiyonu yazın.

TypeScript'te bir diziden undefined değerleri nasıl filtrelerim?

items.filter((x) => x !== undefined), TypeScript 5.5'ten beri undefined içermeyen bir T[] döndürür, çünkü callback'i bir type predicate olarak çıkarır. Eski sürümlerde predicate'i kendiniz yazın: items.filter((x): x is T => x !== undefined).

Coddy programming languages illustration

Coddy ile kodlamayı öğren

BAŞLA