类型放宽
在编译器进行类型推断的过程中,有时会将放宽的源类型作为推断的结果类型
例如:源类型为数字字面量类型0,放宽后的类型为原始类型number
let zero = 0;
等号右侧数字0的类型为数字字面量类型0,推断出的变量zero的类型为放宽的number类型
类型放宽是TypeScript语言的内部行为,它并非是提供给开发者的某种功能特性,因此只需了解即可。
typescript内部存在两种放宽形式:
- 常规类型放宽
- 字面量类型放宽
接下来,我们分别介绍它们。
常规类型放宽
常规类型放宽相对简单,是指编译器在进行类型推断时会将undefined类型和null类型放宽为any类型。
这种情况的类型放宽发生在在非严格类型检查模式下,即没有启用“–strictNullChecks”编译选项时,undefined类型和null类型会被放宽为any类型。
let a = undefined;
const b = null;
在启用了“–strictNullChecks”编译选项时,编译器不再放宽undefined类型和null类型,它们将保持各自的类型。
字面量类型放宽
字面量类型放宽是指编译器在进行类型推断时会将字面量类型放宽为基础原始类型,例如将数字字面量类型0放宽为原始类型number。
并不是所有的字面量类型都会放宽,字面量类型分为可放宽的字面量类型和不可放宽的字面量类型。
每个字面量类型都通过一些内部标识来表示其是否为可放宽的字面量类型。
在一个字面量类型被创建时,就已经确定了其是否为可放宽的字面量类型,并且不能再改变。怎么判断字面量类型是哪一种呢?
判断字面量类型是可放宽的还是不可放宽的遵循以下规则:
- 如果字面量类型源自类型,那么它是不可放宽的字面量类型
- 如果字面量类型源自表达式,那么它是可放宽的字面量类型
const zero:0 = 0;
常量zero的类型为数字字面量类型0,该类型是通过类型注解定义的,即源自类型。因此,类型注解中的数字字面量类型0是不可放宽的字面量类型。
字面量放宽的场景
当编译器进行类型推断时,如果当前表达式的值是可变的,那么将推断出放宽的字面量类型;反之,如果当前表达式的值是不可变的,那么不放宽字面量类型。
在var声明和let声明中,若给变量赋予了初始值,那么推断出的变量类型为放宽的初始值类型。
let num = 0;
var nu = 1;
在const声明中,由于常量的值一经设置就不允许再修改,因此在推断const声明的类型时不会执行类型放宽操作。
const num = 1;