为什么 Typescript 编译器将函数的返回类型推断为“原始类型”,而返回值是已知值?

Meh*_*ash 6 types casting type-conversion typeerror typescript

正如您在下面的代码中看到的,TS 编译器将类型推断为:

const message = Math.random() > 0.5 ? "hello, can you here me" : null;
Run Code Online (Sandbox Code Playgroud)

因此消息变量被推断为"hello, can you here me" | null,这是有道理的,因为有两个绝对可能值,但是在下面的示例中返回值仍然是绝对值,但 getName 类型是string原始类型而不是John Gump

const getName = () => "John Gump";
Run Code Online (Sandbox Code Playgroud)

Tob*_* S. 3

PR/#10676中记录了与此问题相关的所有有关文字类型扩展的规则。


我们看第一个表达式:

const message = Math.random() > 0.5 ? "hello, can you here me" : null;
Run Code Online (Sandbox Code Playgroud)

适用于本声明的第一条规则如下:

表达式中出现的字符串或数字文字的类型是扩展文字类型。

该表达式本身被推断为“加宽文字类型”,这是编译器可以适当加宽的文字类型。

但这在我们的例子中合适吗?公关声明指出

没有类型注释的 const 变量或只读属性推断的类型是初始值设定项的类型。

由于message是变量,表达式的扩展文字类型const的类型不是加宽并保持为"hello, can you here me" | null。

编译器会发现适合let变量的加宽。

let message = Math.random() > 0.5 ? "hello, can you here me" : null;
//  ^? message: string | null
Run Code Online (Sandbox Code Playgroud)

当谈到推断函数返回类型时,PR 指出

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

我们再看一下这个函数:

const getName = () => "John Gump";
Run Code Online (Sandbox Code Playgroud)

我们可以看到,函数返回类型确实是文字类型"John Gump"。这不是联合,也没有上下文类型可以得出返回类型被扩展为其扩展文字类型的结论string。