TypeScript类型推断和字面量类型

6
为什么在第一个示例中,Typescript 推断出字符串类型 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"


1
可能是因为拥有一个常量类型是相当不合逻辑的,而拥有一个可以是两个字符串之一的类型是合乎逻辑的。 - Sami Kuhmonen
1
这是预期行为,感谢我们的上帝和救世主。您可以在此处阅读更多信息:https://github.com/microsoft/TypeScript/pull/11126 或 https://github.com/microsoft/TypeScript/pull/10676 - Juraj Kocan
1
这是你的问题的答案:在这里 - Juraj Kocan
1个回答

4
如果有的话,这个问题的规范答案可能在实现文字扩展算法的拉取请求中找到。首先,我们可以看到你所看到的行为是预期的:
在没有返回类型注释的函数中,如果推断出的返回类型是文字类型(但不是文字联合类型),并且函数没有具有包含文字类型的返回类型的上下文类型,则返回类型会扩展为其扩展文字类型。 () => 'something' 的推断返回类型是字面量 "something",然后扩展为 string。另一方面,(mark: number) => mark >= 10 ? 'good' : 'bad' 的推断返回类型是"good" | "bad",这是一个文字联合类型,因此不会被扩展。
为什么单值文字会被扩展?作者在这条评论中给出了解释:

[Y]ou practically never want the literal type. After all, why write a function that promises to always return the same value? Also, if we infer a literal type this common pattern is broken:

class Base {
  getFoo() {
      return 0;  // Default result is 0
  }
}

class Derived extends Base {
  getFoo() {
      // Compute and return a number
  }
}

If we inferred the type 0 for the return type in Base.getFoo, it would be an error to override it with an implementation that actually computes a number. You can of course add a type annotation if you really want to return a literal type, i.e. 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'

好的,希望有所帮助。祝你好运!


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