类型收窄:是指一个变量被声明(或推断)为联合类型后,在后续代码的条件分支、语句控制流里,能够排除掉不可能的类型,使得联合类型进一步“收窄”为更少的类型。
收窄方式主要有以下几种
- “typeof守卫”类型收窄
- “真值”类型收窄
- “相等性”类型收窄
- “in操作符”类型收窄
- “instanceof”类型收窄
- “赋值"类型收窄
- 使用“类型谓词”收窄
- 通过“公共属性区分联合类型” 收窄
1. “typeof守卫”收窄
let strs: string | nubmer | string[]
if (typeof strs === "object") {
strs // string[] | null
return
}
strs // number
要点: "object"是包含null的
2 真值(Truthiness)收窄
if (strs && typeof strs === "object") {
strs//与上例想比,strs排除了null类型
}
3 相等性收窄
x === y时,双方类型也必然相等,x和y只有string一个共性类型
//x: string | number, y: string | boolean
if (x === y) {
x //string
}
4 "in操作符”收窄
只有Fish有swim成员
type Fish = { swim: () => void };
type Bird = { fly: () => void };
function move(animal: Fish | Bird) {
if ("swim" in animal) {
animal //Fish
}
}
要点:可选属性,会使得类型同时出现在条件的两个分支中,如下例中的Human
type Human = { swim?: () => void; fly?: () => void };
function move(animal: Fish | Bird | Human) {
if ("swim" in animal) {
animal //Fish | Human
} else {
animal //Bird | Human
}
}
4 instanceof 收窄
let x: Date | string ;
if (x instanceof Date) {
x //Date
}
5 赋值收窄
let x: string | number
x = 1;
x // number
6. 使用“类型谓词”收窄
//类型谓词函数
function isFish(pet: Fish | Bird): pet is Fish {
return (pet as Fish).swim !== undefined;
}
if (isFish(pet)) {
pet.swim();
} else {
pet.fly();
}
7. 通过“公共属性区分联合类型” 收窄
在下面的例子中,公共属性是 kind,通过它的取值,可以判断是否有radius或sideLength
interface Circle {
kind: "circle";
radius: number;
}
interface Square {
kind: "square";
sideLength: number;
}
type Shape = Circle | Square;
// 包含 radius成员
if (shape.kind === "circle") {
return Math.PI * shape.radius ** 2;
}