类型推断

在 TypeScript 中,有许多地方会在没有显式类型注释的情况下使用类型推论来提供类型信息。例如,在这段代码中

ts
let x = 3;
let x: number
Try

变量 x 的类型被推断为 number。这种推断发生在初始化变量和成员、设置参数默认值以及确定函数返回值类型时。

在大多数情况下,类型推论非常直接。在接下来的章节中,我们将探索类型推论方式中的一些细微差别。

最佳通用类型

当从多个表达式进行类型推论时,这些表达式的类型会被用来计算一个“最佳通用类型”。例如:

ts
let x = [0, 1, null];
let x: (number | null)[]
Try

为了推断上述示例中 x 的类型,我们必须考虑数组中每个元素的类型。这里我们为数组类型提供了两种选择:numbernull。最佳通用类型算法会考虑每个候选类型,并选出兼容所有其他候选类型的类型。

由于最佳通用类型必须从提供的候选类型中选出,有些情况下类型共享共同结构,但没有一个类型是所有候选类型的超类型。例如:

ts
let zoo = [new Rhino(), new Elephant(), new Snake()];
let zoo: (Rhino | Elephant | Snake)[]
Try

理想情况下,我们可能希望 zoo 被推断为 Animal[],但因为数组中没有严格类型为 Animal 的对象,所以我们不对数组元素类型进行推断。若要修正此问题,请在没有一个类型是所有其他候选类型的超类型时显式提供类型:

ts
let zoo: Animal[] = [new Rhino(), new Elephant(), new Snake()];
let zoo: Animal[]
Try

当找不到最佳通用类型时,最终推断结果为联合数组类型:(Rhino | Elephant | Snake)[]

上下文类型

在某些情况下,TypeScript 中的类型推论也会向“相反方向”工作。这被称为“上下文类型”。上下文类型发生在表达式的类型由其所处位置暗示时。例如:

ts
window.onmousedown = function (mouseEvent) {
console.log(mouseEvent.button);
console.log(mouseEvent.kangaroo);
Property 'kangaroo' does not exist on type 'MouseEvent'.2339Property 'kangaroo' does not exist on type 'MouseEvent'.
};
Try

在这里,TypeScript 类型检查器使用了 Window.onmousedown 函数的类型来推断赋值右侧函数表达式的类型。在进行此操作时,它能够推断出 mouseEvent 参数的 类型,该参数包含 button 属性,但不包含 kangaroo 属性。

这是可行的,因为 window 在其类型定义中已经声明了 onmousedown

ts
// Declares there is a global variable called 'window'
declare var window: Window & typeof globalThis;
// Which is declared as (simplified):
interface Window extends GlobalEventHandlers {
// ...
}
// Which defines a lot of known handler events
interface GlobalEventHandlers {
onmousedown: ((this: GlobalEventHandlers, ev: MouseEvent) => any) | null;
// ...
}

TypeScript 也足够智能,可以在其他上下文中推断类型:

ts
window.onscroll = function (uiEvent) {
console.log(uiEvent.button);
Property 'button' does not exist on type 'Event'.2339Property 'button' does not exist on type 'Event'.
};
Try

基于上述函数被赋值给 Window.onscroll 的事实,TypeScript 知道 uiEvent 是一个 UIEvent,而不是像上一个例子那样的 MouseEventUIEvent 对象不包含 button 属性,因此 TypeScript 将抛出错误。

如果此函数不在上下文类型的位置,则函数参数将隐式具有 any 类型,且不会发出错误(除非你使用了 noImplicitAny 选项)。

ts
const handler = function (uiEvent) {
console.log(uiEvent.button); // <- OK
};
Try

我们还可以显式地为函数参数提供类型信息,以覆盖任何上下文类型:

ts
window.onscroll = function (uiEvent: any) {
console.log(uiEvent.button); // <- Now, no error is given
};
Try

然而,这段代码会记录 undefined,因为 uiEvent 没有名为 button 的属性。

上下文类型适用于许多情况。常见的情况包括函数调用的参数、赋值的右侧、类型断言、对象和数组字面量的成员以及返回语句。上下文类型也会作为最佳通用类型的候选类型。例如:

ts
function createZoo(): Animal[] {
return [new Rhino(), new Elephant(), new Snake()];
}
Try

在这个例子中,最佳通用类型有四个候选者:AnimalRhinoElephantSnake。其中,Animal 可以被最佳通用类型算法选中。

TypeScript 文档是一个开源项目。欢迎通过发送 Pull Request 帮助我们改进这些页面 ❤

此页面的贡献者
RCRyan Cavanaugh (51)
OTOrta Therox (17)
DRDaniel Rosenwasser (10)
MHMartin Hanzel (2)
TLATThink Like a Techy (1)
12+

最后更新:2026 年 3 月 27 日