我可以编写一个抛出异常而不是返回布尔值的类型保护吗?

Clé*_*ent 12 nullable assertions typescript

我有一个在多个函数中使用相同类型保护的类;像这样:

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");
        /* … */
    }
}
Run Code Online (Sandbox Code Playgroud)

我可以重构此代码以将错误移到类型保护中吗?像这样的东西:

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

...我可以这样使用:

class C {
    data: Data | null;

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

    public doB() {
        assertData(this.data);
        /* … */
    }
}
Run Code Online (Sandbox Code Playgroud)

目前我正在使用以下解决方法:

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

……但这迫使我将每次访问都包装this.datamust().

Tit*_*mir 19

编辑 自原始答案以来,打字稿在此 PR 中添加了自定义类型断言的功能

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

Run Code Online (Sandbox Code Playgroud)

游乐场链接

原答案

不幸的是,类型保护的当前语法需要一个if语句才能工作。所以这有效

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
}
Run Code Online (Sandbox Code Playgroud)

但是没有办法让它起作用:

let bar: Data | null = null;
assertData(bar);
bar.foo // bar will still be Data | null
Run Code Online (Sandbox Code Playgroud)