类型推断

1. 是什么?

基于赋值表达式推断类型的能力称之为“类型推断”。

2. 什么场景会类型推断

  • 具有初始化值的变量
  • 有默认值的函数参数
  • 函数返回的类型

字面量类型

字符串字面量类型、数字字面量类型、布尔字面量类型,对应的字符串字面量、数字字面量、布尔字面量分别拥有与其值一样的字面量类型,具体示例如下:

  1. {
  2. let specifiedStr: 'this is string' = 'this is string';
  3. let specifiedNum: 1 = 1;
  4. let specifiedBoolean: true = true;
  5. }

let 和 const 定义的变量的值相同,而变量类型不一致

const 定义一个不可变更的常量,在缺少类型标注的情况下,TS 类型推断出的类型是直接使用赋值字面量的类型。例如:const a = ‘this is str’; 那么 a 的类型就是 ‘this is str’。

但是对于 let,却和 const 不太一样,当使用 let 定义一个变量是,在缺少类型标注的情况下, TS推断出是赋值字面量的类型父类型。例如:let a = ‘this is str’; 那么 a 的类型时 string。

这两种都是符合预期的一种设计。

在补充一句,TS 的字面量子类型转换为父类型的这种设计称之为 “literal widening”,也就是字面量类型的拓宽。

Literal Widening

所有通过 let 或 var 定义的变量、函数的形参、对象的非只读属性,如果满足指定了初始值且未显式添加类型注解的条件,那么它们推断出来的类型就是指定的初始值字面量类型拓宽后的类型,这就是字面量类型拓宽。

Type Widening

对 null 和 undefined 的类型进行拓宽,通过 let、var 定义的变量如果满足未显式声明类型注解且被赋予了 null 或 undefined 值,则推断出这些变量的类型是 any:

  1. {
  2. let x = null; // 类型拓宽成 any
  3. let y = undefined; // 类型拓宽成 any
  4. /** -----分界线------- */
  5. const z = null; // 类型是 null
  6. /** -----分界线------- */
  7. let anyFun = (param = null) => param; // 形参类型是 null
  8. let z2 = z; // 类型是 null
  9. let x2 = x; // 类型是 null
  10. let y2 = y; // 类型是 undefined
  11. }

Type Narrowing

类型缩小