首页 > 解决方案 > 为什么是承诺在可达性分析中没有考虑?

问题描述

假设我们有这个函数:

function returnNever(): never {
    throw new Error();
}

创建 IIFE 时,它之后的代码被标记为不可访问:

(async () => {
    let b: string;
    let a0 = returnNever();
    b = ""; // Unreachable
    b.toUpperCase(); // Unreachable
})();

这按预期工作。请注意,a0推断为 type never

但是,如果returnNever()返回 aPromise<never>并等待,则行为不同:

(async () => {
    let b: string;
    let a1 = await Promise.reject(); // returns Promise<never>
    b = ""; // Not unreachable?
    b.toUpperCase(); // Not unreachable?
})();

在这种情况下,a1也被推断为 type never。但是之后的代码没有被标记为不可访问。为什么?

背景:我最近偶然发现了一些logError类似于以下代码的函数。它在一个catch块内使用。这样,我发现,不是可达性分析,而是明确的分配分析都会受到以下因素的影响:

declare function fetchB(): Promise<string>;
async function logError(err: any): Promise<never> {
    await fetch("/foo/...");
    throw new Error(err);
}
(async () => {
    let b: string;
    try {
        b = await fetchB(); // Promise<string>
    } catch (err) {
        await logError(err); // awaiting Promise<never>
    }
    b.toUpperCase(); // Error: "b" is used before assignment
})();

如果logError是同步的(通过删除与 s 相关的所有awaits 和asyncs logError),则没有错误。此外,如果let b: string更改为let b: string | undefinedundefined则在 try-catch 块之后不会被删除。

似乎有理由在控制流分析的任何方面不考虑返回函数的awaits 。Promise<never>这也可能是一个错误,但我宁愿认为我在这里遗漏了一些细节。

标签: typescriptpromiseasync-awaittype-inferencereachability

解决方案


推荐阅读