打字稿类型推断和文字类型

Jea*_*ant 5 typescript

为什么string在第一个示例中Typescript可以推断类型,而在第二个示例中它能够推断类型文字的精确类型并集'good' | 'bad'呢?

const alwaysSomething = () => 'something' // inferred returned type: string
const moreComplicated = (mark: number) => mark >= 10 ? 'good' : 'bad' // inferred returned type:  'good' | 'bad'
Run Code Online (Sandbox Code Playgroud)

在操场上。如果你悬停alwaysSomething,它显示其类型() => string,但如果你悬停moreComplicated,它显示其类型(mark: number) => "good" | "bad"

jca*_*alz 5

这个问题的规范答案(如果有的话)很可能在实现文字扩展算法的拉取请求中找到。首先我们可以看到您所看到的行为正是预期的:

在没有返回类型注释的函数中,如果推断的返回类型是文字类型(但不是文字联合类型),并且该函数没有返回类型包含文字类型的上下文类型,则返回类型将扩展为它的扩展文字类型。

的推断返回类型() => 'something'是文字"something",然后将其扩展为string。另一方面,推断的返回类型(mark: number) => mark >= 10 ? 'good' : 'bad'is "good" | "bad",它是文字联合类型,因此不会被扩展。

为什么单值文字要加宽?作者有这样的评论:

[Y]你几乎永远不需要文字类型。毕竟,为什么要编写一个承诺始终返回相同值的函数呢?另外,如果我们推断文字类型,那么这种常见模式就被打破了:

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

class Derived extends Base {
  getFoo() {
      // Compute and return a number
  }
}
Run Code Online (Sandbox Code Playgroud)

0如果我们推断出 in 中返回类型的类型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'
Run Code Online (Sandbox Code Playgroud)

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