Type guard, TypeScript'in anladığı bir çalışma zamanı kontrolüdür; bu yüzden kontrol edilen dalın içinde tipi daraltır. typeof, instanceof ve in yerleşik guard'lardır; geri kalan her şey için dönüş tipi bir type predicate olan, value is Type, bir fonksiyon yazarsınız.
isUser çalışma zamanında düz bir boolean döndürür. value is User dönüş tipi derleyiciye true sonucunun neyi kanıtladığını söyler ve ardından her if (isUser(x)) ifadesi x değerini User tipine daraltır.
Yerleşik Type Guard'lar
Bu kontroller hiçbir yardımcı fonksiyon olmadan daraltır:
| Guard | Örnek | Ne için kullanılır |
|---|---|---|
typeof | typeof x === "number" | primitive'ler ve fonksiyonlar |
instanceof | x instanceof Date | sınıf örnekleri |
in | "email" in x | nesne union'ları, unknown nesnelerin özellikleri |
Array.isArray | Array.isArray(x) | diziler |
| Eşitlik | x === null, x.kind === "circle" | null/undefined, literal etiketler |
| Truthiness | if (x) | null ve undefined değerlerini çıkarmak |
Hepsi sıradan JavaScript olarak çalışır. TypeScript'in eklediği daraltmadır: kontrolü okur ve her daldaki tipi ayarlar. Biçimlerin tam listesi tip daraltma sayfasında. Özel bir guard, tek bir ifadeye sığmayan ya da yeniden kullanmak istediğiniz kontroller içindir.
Bir Type Predicate Yazmak
Bir type predicate parameterName is Type biçimindedir ve dönüş tipi olarak boolean yerine geçer. Daraltma iki yönde çalışır: true sonucu Type tipine daraltır, false ise Type tipini bir union'dan çıkarır.
Bir guard'ı filter metoduna vermek doğru tiplenmiş bir dizi verir. TypeScript 5.5'ten beri derleyici basit arrow function'lardan da bir predicate çıkarır, bu yüzden pets.filter((p) => p.kind === "cat") isimli bir guard olmadan Cat[] döndürür.
Predicate'in tipi parametrenin tipine uymalıdır: function f(x: string): x is number TS2677 hatasıdır, A type predicate's type must be assignable to its parameter's type.
Derleyici Guard'ınıza Güvenir
TypeScript bir guard'ın boolean döndürdüğünü kontrol eder. Boolean'ın doğru olduğunu kontrol etmez. Yanlış değerler için true döndüren bir guard tiplerin yalan söylemesine yol açar ve program hiçbir derleme hatası olmadan çalışma zamanında başarısız olur.
data.price.toFixed(2) çalışma zamanında TypeError: Cannot read properties of undefined (reading 'toFixed') fırlatır. Derleyici data.price değerini bir number olarak kabul etti, çünkü guard öyle söyledi. Kodun geri kalanının güvendiği her özelliği kontrol edin; guard'ları küçük, test edilmiş ve tanımladıkları tipe yakın tutun.
Bir Nesnenin Belirli Bir Tipte Olup Olmadığını Kontrol Etmek
Çoğu özel guard'ın arkasındaki soru budur: veri unknown olarak gelir (JSON.parse, fetch, localStorage, bir mesaj üzerinden) ve interface'inizle eşleşip eşleşmediğini bilmeniz gerekir. Tarif:
typeof value === "object" && value !== null(bir nesne,nulldeğil).- Her zorunlu özellik için
"prop" in value.unknownüzerindein, özelliği tipeunknownolarak ekler. - Her özelliğin tipi için
typeof value.prop === "..."(ya da iç içe bir guard). - Diziler için
Array.isArray(value.items) && value.items.every(isItem).
Büyük veya derin iç içe biçimlerde bunları elle yazmak yorucu hale gelir. Zod veya Valibot gibi şema kütüphaneleri biçimi bir kez tanımlamanıza izin verir ve size hem çalışma zamanı kontrolünü hem de TypeScript tipini verir.
Assertion Fonksiyonları: asserts value is Type
Bir assertion fonksiyonu kontrol başarısız olursa hata fırlatır, aksi halde normal şekilde döner. Dönüş tipi asserts value is Type (veya asserts condition) olur ve çağrıdan sonraki her şey, bir if gerekmeden daraltılır.
İnsanları şaşırtan bir kural var: bir assertion fonksiyonu, açık bir tipe sahip bir ad üzerinden çağrılmalıdır. Notasyonsuz bir const arrow function, const check = (v: unknown): asserts v is string => {...}, çağrı yerinde TS2775 hatası verir: Assertions require every name in the call target to be declared with an explicit type annotation. Bir function bildirimi kullanın ya da sabite bir fonksiyon tipi notasyonu yazın.
Guard'lar, Assertion'lar ve Cast'ler
| Araç | Çalışma zamanı kontrolü? | Daralttığı yer | Başarısızlıkta |
|---|---|---|---|
Yerleşik guard (typeof, in...) | Evet | dalın içinde | diğer dala gider |
value is T fonksiyonu | Evet (sizin kodunuz) | dalın içinde | diğer dala gider |
asserts value is T fonksiyonu | Evet (sizin kodunuz) | çağrıdan sonra | hata fırlatır |
value as T | Hayır | ifadenin kendisi | hiçbir şey: yanlış tip yayılır |
Bir type assertion (as) hiçbir şeyi kontrol etmeden tipi değiştirir. Verinin dışarıdan geldiği bir sınırda, aynı fikrin güvenli sürümü bir guard ya da bir assertion fonksiyonudur.
Sınıflarda this Tabanlı Guard'lar
Bir metot, this is Type ile üzerinde çağrıldığı nesneyi daraltabilir. Sınıf hiyerarşilerinde kullanışlıdır:
class FileNode {
constructor(public name: string) {}
isDirectory(): this is DirectoryNode {
return this instanceof DirectoryNode;
}
}
class DirectoryNode extends FileNode {
children: FileNode[] = [];
}
function count(node: FileNode): number {
return node.isDirectory() ? node.children.length : 0; // node: DirectoryNode in the true branch
}
Sıkça Sorulan Sorular
TypeScript'te type guard nedir?
TypeScript'in bir tipi daraltmak için kullandığı her çalışma zamanı kontrolüdür: typeof x === "string", x instanceof Date, "id" in x, Array.isArray(x) ya da dönüş tipi x is User gibi bir type predicate olan bir fonksiyona yapılan çağrı. Kontrol edilen dalın içinde değişken daha dar tipe sahip olur.
TypeScript'te bir nesnenin belirli bir tipte olup olmadığını nasıl kontrol ederim?
Tipler çalışma zamanında var olmaz, bu yüzden özellikleri kontrol edersiniz: typeof value === "object", value !== null ve her zorunlu özelliği in ve typeof ile test eden bir isUser(value: unknown): value is User fonksiyonu yazın. if (isUser(x)) sonrasında x tipi User olur. Sınıflar için x instanceof MyClass yeterlidir.
TypeScript'te "value is Type" ne anlama gelir?
Bir fonksiyonun dönüş tipi olarak kullanılan bir type predicate'tir. Fonksiyon çalışma zamanında yine bir boolean döndürür, ama true döndürdüğünde TypeScript çağrı yerinde argümanı Type tipine, false döndürdüğünde de union'ın diğer üyelerine daraltır. Derleyici fonksiyon gövdesini doğrulamaz, bu yüzden kontrolün doğru olması gerekir.
Type guard ile assertion fonksiyonu arasındaki fark nedir?
Bir type guard (x is T) bir boolean döndürür ve bir if içinde daraltır. Bir assertion fonksiyonu (asserts x is T) hiçbir şey döndürmez ve kontrol başarısız olduğunda hata fırlatır; bu yüzden çağrıdan sonraki her şey if olmadan daraltılır. Dallanma için guard'ları, "bu doğru olmalı, yoksa dur" için assertion'ları kullanın.
TypeScript'te bir nesnenin bir interface'i implement ettiğini kontrol edebilir miyim?
Doğrudan değil: interface'ler silinir ve instanceof onları kabul etmez. Interface'in özelliklerini kontrol eden bir type guard yazın ya da bir literal etiket özelliği (kind: "user") ekleyip onu karşılaştırın. Zod gibi şema kütüphaneleri tek bir tanımdan hem kontrolü hem tipi üretir.