TS复习笔记(1):类型收窄

46 阅读2分钟

类型收窄:是指一个变量被声明(或推断)为联合类型后,在后续代码的条件分支、语句控制流里,能够排除掉不可能的类型,使得联合类型进一步“收窄”为更少的类型。

收窄方式主要有以下几种

  1. “typeof守卫”类型收窄
  2. “真值”类型收窄
  3. “相等性”类型收窄
  4. “in操作符”类型收窄
  5. “instanceof”类型收窄
  6. “赋值"类型收窄
  7. 使用“类型谓词”收窄
  8. 通过“公共属性区分联合类型” 收窄

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;
}