gpt4 book ai didi

TypeScript 从不进行类型推断

转载 作者:搜寻专家 更新时间:2023-10-30 20:31:26 25 4
gpt4 key购买 nike

谁能解释一下为什么给出以下代码:

let f = () => {
throw new Error("Should never get here");
}

let g = function() {
throw new Error("Should never get here");
}

function h() {
throw new Error("Should never get here");
}

推断出以下类型:

  • f() => 从不
  • g() => 从不
  • h() => void

我希望 h 的类型也为 () => never

谢谢!

最佳答案

好问题。区别在于fg是函数表达式,其中h是函数声明。当一个函数是throw-only 时,如果它是一个表达式,它会得到类型never,如果它是一个声明,它会得到类型void

当然,上面的段落实际上并没有帮助。为什么函数表达式和函数声明之间的行为存在差异?让我们看看每种情况下的一些反例。

坏主意 #1:让抛出函数表达式返回 void

考虑一些代码:

function iif(value: boolean, whenTrue: () => number, whenFalse: () => number): number {
return value ? whenTrue() : whenFalse();
}
let x = iif(2 > 3,
() => { throw new Error("haven't implemented backwards-day logic yet"); },
() => 14);

这段代码可以吗?它应该是!当我们认为不应调用该函数或仅应在错误情况下调用该函数时,通常会编写一个throwing 函数。但是,如果函数表达式的类型是 void,则对 iif 的调用将被拒绝。

因此从这个例子中可以清楚地看出,仅 throw 的函数表达式应该返回 never,而不是 void。实际上,这应该是我们的默认假设,因为这些函数符合 never 的定义(在正确类型的程序中,无法观察到 never 类型的值)。

坏主意 #2:使抛出函数声明返回 never

阅读上一节后,您应该会说“太好了,那为什么所有的抛出函数都不返回 never?”

简短的回答是,这样做是一个重大的突破性变化。有很多代码(尤其是 abstract 关键字之前的代码)看起来像这样

class Base {
overrideMe() {
throw new Error("You forgot to override me!");
}
}

class Derived extends Base {
overrideMe() {
// Code that actually returns here
}
}

但是返回 void 的函数不能替代返回 never 的函数(记住,在正确类型的程序中,never无法观察到值),因此使 Base#overrideMe 返回 never 可防止 Derived 提供任何非 never 实现的那种方法。

通常,虽然总是抛出的函数表达式通常作为Debug.fail的占位符存在,但总是抛出的函数声明是极少。表达式经常被别名或忽略,而声明是静态的。今天抛出的函数声明实际上明天可能会做一些有用的事情;在没有返回类型注解的情况下,提供的更安全的方法是 void(即暂时不要查看此返回类型)而不是 never(即此函数是一个会吃掉当前执行堆栈的黑洞)。

关于TypeScript 从不进行类型推断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40251524/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com