typescript - Boolean yerine istisna fırlatan bir tip koruyucu yazabilir miyim?


Aynı tür koruyucuyu birden fazla fonksiyonda kullanan bir sınıfım var; şöyle bir şey:

function validData(d: Data | null): d is Data {
    return d !== null;
}

class C {
    data: Data | null;

    public doA() {
        if (!validData(this.data))
            throw new Error("Invalid data");
        /* … */
    }

    public doB() {
        if (!validData(this.data))
            throw new Error("Invalid data");
        /* … */
    }
}

Bu kodu hata kontrolünü tür koruyucusuna taşımak için yeniden düzenleyebilir miyim? Şöyle bir şey:

function assertData(d: Data | null): ??? {
    if (d === null)
        throw new Error("Invalid data");
}

…bunu şöyle kullanabilirdim:

class C {
    data: Data | null;

    public doA() {
        assertData(this.data);
        /* … */
    }

    public doB() {
        assertData(this.data);
        /* … */
    }
}

Şu anda aşağıdaki geçici çözümü kullanıyorum:

function must(d: Data | null): Data {
    if (d === null)
        throw new Error("Invalid data");
    return d;
}

… ama bu, this.data'ye yapılan her erişimi must() içine sarmalamamı zorunlu kılıyor.

Cevap #1

Düzenle Orijinal cevaptan bu yana, TypeScript bu PR'de özel tip doğrulama yeteneğini ekledi

type Data = { foo: string };

function assertData(d: Data | null): asserts d is Data {
    if (d == null)
        throw new Error("Invalid data");
}
// Use
declare var bar: Data | null;
bar.foo // error as expected
assertData(bar)
bar.foo // inferred to be Data

Oyun Alanı Bağlantısı

Orijinal cevap

Ne yazık ki, tip koruyucular için mevcut sözdizimi, çalışmaları için bir if ifadesi gerektirir. Yani bu çalışır

type Data = { foo: string };
function assertData(d: Data | null): d is Data {
    if (d == null)
        throw new Error("Invalid data");
    return true;
}
// Use
let bar: Data | null = null;
if (assertData(bar)) {
    bar.foo // inferred to be Data
}

Ama bunu çalıştırmanın bir yolu yok:

let bar: Data | null = null;
assertData(bar);
bar.foo // bar will still be Data | null

İlgili makaleler