为什么类型标在第一个示例中推断类型string,而在第二个示例中它能够推断类型文字'good' | 'bad'的精确类型组合?
const alwaysSomething = () => 'something' // inferred returned type: string
const moreComplicated = (mark: number) => mark >= 10 ? 'good' : 'bad' // inferred returned type: 'good' | 'bad'在操场上。如果将alwaysSomething悬停,则显示其类型为() => string,但如果悬停moreComplicated,则显示其类型为(mark: number) => "good" | "bad"。
发布于 2019-09-23 14:15:21
这个问题的典型答案,如果有,很可能在拉请求实现文字加宽算法中找到。首先,我们可以看到,你所看到的行为就是你的意图:
在没有返回类型注释的函数中,如果推断的返回类型是文字类型(但不是文字联合类型),并且函数没有包含文字类型的返回类型的上下文类型,则返回类型将被拓宽为其扩大的文字类型。
推断的() => 'something'返回类型是文字"something",然后将其扩展为string。另一方面,推断出的(mark: number) => mark >= 10 ? 'good' : 'bad'返回类型是"good" | "bad",这是一个文本联合类型,因此没有扩大。
为什么单值文字会变广?这是作者的这句话:
你根本就不想要文字类型。毕竟,为什么要编写一个承诺总是返回相同值的函数呢?另外,如果我们推断出一个文字类型,这个常见的模式就被打破了: 类基{ getFoo() {返回0;//默认结果是0}类派生扩展基{ getFoo() { //计算并返回一个数字}} 如果我们推断
0类型为Base.getFoo中的返回类型,则使用实际计算数字的实现覆盖它将是错误的。当然,如果您真的想返回一个文本类型,即getFoo(): 0 { return 0; },可以添加一个类型注释。
为什么字面上的联盟没有扩大呢?这里是作者的稍后的评论:
在
return cond ? 0 : 1的情况下,推断的返回类型是0 | 1。我认为在这种情况下,根本不清楚我们应该扩大到基元类型。毕竟,使用返回类型的0 | 1,实际上有意义的信息将从函数中传递出去。
因此,这是一个实用性问题:人们很少打算返回单个文字类型,但他们经常打算返回文本类型的联合。由于类型推断总是可以被显式类型注释覆盖,所以您可以处理这种启发给出错误结果的情况:
const alwaysSomething = (): 'something' => 'something' // inferred returned type:
const moreComplicated = (mark: number): string => mark >= 10 ? 'good' : 'bad'好吧,希望能帮上忙。祝好运!
https://stackoverflow.com/questions/58061286
复制相似问题