Menu

TypeScript never Tipi: Kapsamlı Kontroller ve never ile void

never, hiç değeri olmayan tiptir. Hiç bitmeyen fonksiyonların dönüş tipi, daraltma her durumu elediğinde geriye kalan tip ve kapsamlı switch kontrollerinin arkasındaki araçtır. Nereden geldiğini ve void'den nasıl ayrıldığını öğrenin.

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

never, hiç değeri olmayan tiptir. Dönüş tipi never olan bir fonksiyon asla normal şekilde dönmez: hata fırlatır ya da sonsuza kadar çalışır. never tipindeki bir değişken çalışamayacak kodu işaretler ve kapsamlı (exhaustive) kontrolleri mümkün kılan da budur.

return fail(...), number döndüren bir fonksiyonda derlenir, çünkü never her tipe atanabilir: never tipinde bir değer asla gerçekten ortaya çıkamaz.

Hiç Dönmeyen Fonksiyonlar

İki tür fonksiyon asla sonuna ulaşmaz: her zaman hata fırlatan ve sonsuz döngü içeren. Derleyici bu iddiayı kontrol eder. Sonuna ulaşılabilen never notasyonlu bir fonksiyon TS2534 hatasıdır, A function returning 'never' cannot have a reachable end point.

function fail(message: string): never {
  throw new Error(message);
}

function runForever(): never {
  while (true) {
    // poll, serve requests...
  }
}

Çıkarım sözdizimine göre değişir. Yalnızca hata fırlatan bir function declaration void döndüren olarak çıkarılır; yalnızca hata fırlatan bir arrow function veya function expression ise never olarak çıkarılır:

function f1() { throw new Error("x"); }       // () => void
const f2 = () => { throw new Error("x"); };   // () => never

Daraltma, bir çağrıyı yalnızca çağrılan adın never döndüren açık bir tipi olduğunda çıkmaz sokak olarak ele alır: yukarıdaki fail gibi : never notasyonlu bir function declaration ya da tip notasyonlu bir değişken, const fail: (m: string) => never = (m) => { throw new Error(m); }. Çıkarılmış bir never sayılmaz; yalnızca arrow'un notasyonlu olduğu, değişkenin ise olmadığı const fail = (m: string): never => ... de sayılmaz.

never ile void

voidnever
Fonksiyon biterevethayır (hata fırlatır veya sonsuza kadar döner)
Çalışma zamanındaki değerundefinedyok: çağrı asla bir değer üretmez
Çağrıdan sonraki kodulaşılabilirulaşılamaz
Diğer tiplere atanabiliryalnızca void, unknown, anyher tipe
Tipik kullanımcallback'ler, event handler'lar, yan etkili fonksiyonlarfail(), assertNever(), sonsuz döngüler

Pratik fark daraltmada görünür. if (!user) fail("no user") sonrasında derleyici, sonraki satırda user değerinin tanımlı olduğunu yalnızca fail bir never döndürüyorsa bilir. void dönüşünde çalışmanın devam edebileceğini varsayar.

never ile Kapsamlı Kontroller

Bir union üzerindeki switch ifadesinin her case dalı değeri daraltır. Her üye ele alındığında default içinde kalan şey never olur. Onu bir never değişkenine atamak, "her durumu ele aldım" iddiasını derleyicinin doğruladığı bir şeye dönüştürür:

Şimdi union'a bir case eklemeden üçüncü bir üye ekleyin:

index.ts(18,26): error TS2345: Argument of type '{ kind: "triangle"; base: number; height: number; }' is not assignable to parameter of type 'never'.

Hata, unuttuğunuz üyeyi adıyla söyler. case "triangle": return (shape.base * shape.height) / 2; ekleyin, kod yeniden derlenir. assertNever yardımcısı aynı kontrolün yeniden kullanılabilir biçimidir ve throw ifadesi çalışma zamanında da önemlidir: JSON'dan ya da eski bir istemciden gelen veriler, tiplerin imkansız dediği bir kind içerebilir. Bu kalıp discriminated union'ların omurgasıdır.

never'a Kadar Daraltmak

Aynı şey yalnızca switch ile değil, her daraltmada olur. Her olasılık elendiğinde değişkenin tipi never olur:

Daha sonra parametreyi string | number | boolean | bigint olarak genişletirseniz const nothing: never = x satırı hata verir ve güncellenmesi gereken fonksiyonu gösterir.

never Union'larda Kaybolur

never boş değer kümesidir, bu yüzden onu bir union'a eklemek hiçbir şeyi değiştirmez: string | never sadece string olur. Conditional tipler union'ları bu şekilde filtreler. never döndüren bir dal o üyeyi kaldırır:

Yerleşik Exclude<T, U> ve Extract<T, U> tam olarak böyle çalışır. Bir intersection'da ise tersidir: string & never sonucu never olur.

İmkansız Tipler never Olur

Hiçbir değerin karşılayamayacağı bir intersection never tipine indirgenir:

type A = string & number;                   // never
type B = { kind: "a" } & { kind: "b" };     // never

Bir B değerinin özelliğini okumak nedeni bildirir: Property 'kind' does not exist on type 'never'. The intersection 'B' was reduced to 'never' because property 'kind' has conflicting types in some constituents. Oluşturduğunuz bir tip never çıkarsa, birbiriyle çelişen iki parça arayın.

never, unknown ve any

TipTuttuğu değerlerAtanabildiği tiplerKabul ettiği
unknownher değeryalnızca unknown ve anyher şey
anyher değernever dışında her şeyher şey
neverhiç değer yokher şeyyalnızca never

unknown tip hiyerarşisinin tepesi, never ise dibidir. any hiyerarşinin hiç parçası değildir: kontrolleri kapatır.

Sıkça Sorulan Sorular

TypeScript'te never tipi nedir?

never, hiç değeri olmayan tiptir. Ona hiçbir şey atanamaz (başka bir never dışında) ve kendisi her tipe atanabilir. Her zaman hata fırlatan ya da sonsuza kadar dönen fonksiyonların dönüş tipi olarak, daraltma her olasılığı eledikten sonra bir değişkenin tipi olarak ve string & number gibi imkansız tiplerin sonucu olarak karşınıza çıkar.

never ile void arasındaki fark nedir?

void döndüren bir fonksiyon normal şekilde biter; sadece işe yarar bir değer döndürmez (çalışma zamanında undefined döndürür). never döndüren bir fonksiyon ise hiç bitmez: hata fırlatır ya da sonsuza kadar çalışır. Bir never fonksiyonu çağrısından sonraki koda ulaşılamaz ve TypeScript daraltma sırasında onu böyle ele alır.

TypeScript'te kapsamlı (exhaustive) kontrol nasıl yapılır?

Bir union üzerindeki switch ifadesinin default dalında değeri never tipinde bir değişkene atayın ya da hata fırlatan bir assertNever(value: never): never fonksiyonuna verin. Her durum ele alınmışsa değer orada never olur ve kod derlenir. Bir durum eksikse derleyici, eksik üyenin never tipine atanamadığını bildirir.

Tipim neden never?

Genellikle TypeScript her seçeneği daralttığı için (örneğin bir string | number üzerinde typeof x === "string" ve typeof x === "number" kontrollerinden sonra) ya da bir intersection imkansız olduğu için: string & number veya ortak bir özelliği çelişen literal tiplere sahip iki nesne tipi. Hangi adımın onu ürettiğini görmek için editörde tipin üzerine gelin.

"is not assignable to type never" ne anlama gelir?

Kod, yalnızca never tipine izin verilen bir yere gerçek bir değer koymaya çalıştı. Kapsamlı bir kontrolde bu, bir union üyesinin ele alınmadığı anlamına gelir. Başka yerlerde çoğu zaman bir dizinin never[] olarak çıkarıldığı ya da bir intersection'ın never tipine çöktüğü anlamına gelir; bir notasyon ekleyin ya da çelişen tipleri düzeltin.

Coddy programming languages illustration

Coddy ile kodlamayı öğren

BAŞLA