TS官方手册:TypeScript: Handbook - The TypeScript Handbook (typescriptlang.org)
一个变量如果声明为联合类型,而后续操作需要针对其具体的单一类型做不同处理,这个过程就叫做类型收窄(Narrowing
)。
常见的做法或情形有以下:
typeof 类型保护(type guards)
typeof
是 JS 中的操作符,需要注意typeof
对象、数组、null
都会返回object
。
真值收窄(Truthiness narrowing)
0
,NaN
,""
,0n
,null
,undefined
都会被隐式转换为false
,属于假值,其它的值是真值。依据这个规则也可以收窄类型。
等值收窄(Equality narrowing)
在 JS 中,全等判断符===
要求两边类型一致,以此也可以排除一些类型,从而实现收窄类型。
in 操作符收窄
in操作符检查指定的属性是否在指定的对象或其原型链中。
instanceof 收窄
instanceof
运算符用于检测构造函数的 prototype
属性是否出现在某个实例对象的原型链上。
赋值语句(Assignments)
TS 可以根据赋值语句的右值的类型收窄左值。
控制流分析(Control flow analysis)
基于可达性的代码分析就是控制流分析,关注代码中的if
,while
等条件控制语句。
如果代码达到了某个区域,而根据条件控制语句可以得知:如果变量X是类型A,无法到达此区域,那么就可以推断出到达此区域的变量X的类型不可能是A。
于是类型收窄。
function padLeft(padding: number | string, input: string) {
if (typeof padding === "number") {
return new Array(padding + 1).join(" ") + input;
}
return padding + input;
}
在第一个 if
语句里,因为有 return
语句,TypeScript 就能通过代码分析,判断出在剩余的部分 return padding + input
,如果 padding 是 number
类型,是无法达到 (unreachable) 这里的,所以在剩余的部分,就会将 number
类型从 number | string
类型中删除掉。