type guards (类型守卫) 和 narrowing
通过 if
条件语句对类型进行判断,TypeScript会对变量的类型进行分析,以明白这个分支下变量的具体类型,这个过程叫做 type guards
。而这整个由不确定类型到确定具体类型到过程就叫做 narrowing
,下面有几种方式可以对类型进行校验。
typeof
守卫
可以通过 typeofe
运算符对类型进行最基础对判断:
string
number
bigint
boolean
symbol
undefined
object
function
Truthiness narrowing(是否为真)
在 if
表达式内,JavaScript 对条件是否为真对判断并不是决定对,它会把非 boolean
类型对表达式转化为 boolean
类型进行判断。下面的值会被转化为 false
:
0
NaN
""
(空字符串)0n
(大整型0)null
undefined
除了上面这些值会被转化为false
,其它都会被转发为true
。
Equality narrowing(是否相等)
我们可以通过 ===
,!==
,==
,!=
对类型进行收缩。比如:1
2
3
4
5
6
7
8
9
10
11
12
13
14function example(x: string | number, y: string | boolean) {
if (x === y) {
// We can now call any 'string' method on 'x' or 'y'.
x.toUpperCase();
// ^?
y.toLowerCase();
// ^?
} else {
console.log(x);
// ^?
console.log(y);
// ^?
}
}
instanceof
narrowing(原型校验)
这种方式用来检查通过new
对方式创建出来对对象对类型。1
2
3
4
5
6
7function logValue(x: Date | string) {
if (x instanceof Date) {
console.log(x.toUTCString());
} else {
console.log(x.toUpperCase());
}
}
赋值操作
TypeScript会根据赋值操作符=
右边对类型决定变量的类型1
let x = Math.random() < 0.5 ? 10 : "hello world!";
这里的 x
会被推断为 string | number
两种类型。
类型断言
对于自定义类型,可以通过 parameterName is Type
的方式断言某个变量是 Type
类型,其中 parameterName
必须为函数的参数1
2
3function isFish(pet: Fish | Bird): pet is Fish {
return (pet as Fish).swim !== undefined;
}
联合类型
通过 |
符号来表示字面类型的组合,如:1
2
3
4
5interface Shape {
kind: "circle" | "square";
radius?: number;
sideLength?: number;
}
never
类型
never
类型表示一个不应该存在的状态,如:1
2
3
4
5
6
7
8
9
10
11
12
13type Shape = Circle | Square;
function getArea(shape: Shape) {
switch (shape.kind) {
case "circle":
return Math.PI * shape.radius ** 2;
case "square":
return shape.sideLength ** 2;
default:
const _exhaustiveCheck: never = shape;
return _exhaustiveCheck;
}
}