type guards (类型守卫) 和 narrowing
通过 if 条件语句对类型进行判断,TypeScript会对变量的类型进行分析,以明白这个分支下变量的具体类型,这个过程叫做 type guards 。而这整个由不确定类型到确定具体类型到过程就叫做 narrowing ,下面有几种方式可以对类型进行校验。
typeof 守卫
可以通过 typeofe 运算符对类型进行最基础对判断:
stringnumberbigintbooleansymbolundefinedobjectfunction
Truthiness narrowing(是否为真)
在 if 表达式内,JavaScript 对条件是否为真对判断并不是决定对,它会把非 boolean 类型对表达式转化为 boolean 类型进行判断。下面的值会被转化为 false :
0NaN""(空字符串)0n(大整型0)nullundefined
除了上面这些值会被转化为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;
}
}