为什么在使用箭头函数时,TypeScript不能通过控制流和never缩小类型?

5
Typescript在调用fail时拒绝缩小,但在调用fail2时会缩小。这是Typescript的一个错误吗?
const fail = (message?: string): never => {
    throw new Error(message);
};

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

const getData = (): string | null => {
    return "the-data";
}



export const loadDataOrError = (): string => {
    const data = getData();

    if (data === null) {
        // Swap the below and see that it works
         
        // fail2();
        fail();
    }

    // This errors
    return data;
};

这里是一个游乐场,如果你想尝试切换注释并看到错误消失。

为了更清晰地展示,附上截图
带有错误

With an error

没有错误

Without an error


1
即使fail可以被重新赋值,新的值仍然会返回never,所以这不是一个好的理由。在您的示例中,您使用了设计上不合理的as,因此显然会导致奇怪的行为。 - Guillaume Brunerie
同意@GuillaumeBrunerie。也不要忘记它是一个“const”,所以整个参数都是不合逻辑的。 - Zachiah
我认为你应该提交一个问题报告。这不是正常的。 - geoffrey
刚刚发现了这个问题(https://github.com/microsoft/TypeScript/issues/52784)。我想我会回答自己的问题。 - Zachiah
1个回答

5
根据这个开放的GitHub问题,这是TypeScript中类型缩小目前的限制。如果您想解决它,可以像这样明确注释箭头函数类型:
const fail: (message?: string) => never = (message) => {
    throw new Error(message)
}

1
是的,这完全取决于你所调用的事物的显式类型注释。这是断言函数的一个相当令人烦恼的限制。 - jcalz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接