TypeScript 类型推断
简介:在本教程中,你将了解 TypeScript 中的类型推断。
类型推断描述了当你没有明确指定数据类型时,TypeScript 在何处以及如何推断类型。
基本类型的推断
当你声明一个变量时,你可以使用类型注释来显式地指定它的类型。例如:
let counter: number;
但是,如果将 counter
变量初始化为数字,TypeScript 会推断它的类型为 number
。例如:
let counter = 0;
它等效于以下语句:
let counter: number = 0;
同样,当你为函数参数赋值时,TypeScript 会将参数的类型推断为默认值的类型。例如:
function setCounter(max=100) {
// ...
}
在此示例中,TypeScript 将 max
参数的类型推断为 number
。
同样,TypeScript 将以下 increment()
函数的返回类型推断为 number
:
function increment(counter: number) {
return counter++;
}
它与以下内容效果相同:
function increment(counter: number) : number {
return counter++;
}
最通用类型算法
请看如下赋值语句:
let items = [1, 2, 3, null];
为了推断 items
变量的类型,TypeScript 需要考虑数组中每个元素的类型。
它使用最通用类型算法来分析每个候选类型,并选择与所有其他候选类型兼容的类型。
对于如上的例子,TypeScript 选择数字数组类型( number[]
) 作为最通用的类型。
如果将字符串添加到 items
数组,TypeScript 会将它的类型推断为数字和字符串组成的数组:(number | string)[]
。
let items = [0, 1, null, 'Hi'];
当 TypeScript 找不到最通用类型时,它会返回联合数组类型。例如:
let arr = [new Date(), new RegExp('\d+')];
在此示例中,TypeScript 将 arr
的类型推断为 (RegExp | Date)[]
。
基于上下文的类型推断
TypeScript 根据变量的位置来推断它们的类型。这种机制称为上下文类型推断。例如:
document.addEventListener('click', function (event) {
console.log(event.button); //
});
在这个例子中,TypeScript 知道 event
参数是 MouseEvent
的实例,因为是 click
事件。
但是,当你将 click
事件更改为 scroll
事件时,TypeScript 会报错:
document.addEventListener('scroll', function (event) {
console.log(event.button); // compiler error
});
错误:
Property 'button' does not exist on type 'Event'.(2339)
TypeScript 知道此时 event
是 UIEvent
的实例,而不是 MouseEvent
的实例。并且 UIEvent
没有 button
属性,因此,TypeScript 会抛出一个错误。
你会在多种场景下发现上下文类型推断,例如函数调用时的传参、类型声明、对象的属性和数组的元素,return 语句以及赋值语句。
类型推断与类型注解
下面显示类型推断和类型注释之间的区别:
类型推断 | 类型注解 |
---|---|
TypeScript 猜测类型 | 你明确地告诉 TypeScript 类型 |
那么,什么时候分别使用类型推断和类型注解呢?
在实践中,你应该始终尽可能多地使用类型推断。同时,在以下情况下使用类型注释:
- 当你声明一个变量并稍后为其赋值时。
- 当你想要一个无法推断的变量时。
- 当一个函数返回
any
类型而你需要明确它的数值类型时。
概括
- 当你初始化变量、设置参数默认值和决定函数返回类型时,就会发生类型推断。
- TypeScript 使用最通用类型算法来选择与所有变量兼容的最佳候选类型。
- TypeScript 还根据变量的位置使用上下文类型推断来推断变量的类型。