Typescript 从入门到放弃系列(九)-类型保护

189 阅读1分钟

通过判断识别所执行的代码块,自动识别变量属性和方法

一.typeof类型保护

function double(val: number | string) {
    if (typeof val === 'number') {
        val
    } else {
        val
    }
}

二.instanceof类型保护

class Cat { }
class Dog { }

const getInstance = (clazz: { new(): Cat | Dog }) => {
    return new clazz();
}
let r = getInstance(Cat);
if(r instanceof Cat){
    r
}else{
    r
}

三.in类型保护

interface Fish {
    swiming: string,
}
interface Bird {
    fly: string,
    leg: number
}
function getType(animal: Fish | Bird) {
    if ('swiming' in animal) {
        animal // Fish
    } else {
        animal // Bird
    }
}

四.可辨识联合类型

interface WarningButton {
    class: 'warning'
}
interface DangerButton {
    class: 'danger'
}
function createButton(button: WarningButton | DangerButton) {
    if (button.class == 'warning') {
        button // WarningButton
    } else {
        button // DangerButton
    }
}

五.null保护

const addPrefix = (num?: number) => {
  num = num || 1.1;
  function prefix(fix: string) {
      return fix + num?.toFixed()
  }
  return prefix('james');
}
console.log(addPrefix()); // james1

这里要注意的是ts无法检测内部函数变量类型

六.自定义类型保护

interface Fish {
  swimming: string,
}
interface Bird {
  fly: string,
  leg: number
}
function isFish(animal: Fish | Bird):animal is Bird {
  return 'swimming' in animal
}
function getAnimal (animal:Fish | Bird){
  console.log(isFish(animal)); // false
  if(isFish(animal)){
      animal
  }else{
      animal
  }
}
console.log(getAnimal({fly: "fly", leg: 2}));

七.完整性保护

interface ICircle {
    kind: 'circle',
    r: number
}
interface IRant {
    kind: 'rant',
    width: number,
    height: number
}
interface ISquare {
    kind: 'square',
    width: number
}
type Area = ICircle | IRant | ISquare
const isAssertion = (obj: never) => { }
const getArea = (obj: Area) => {
    switch (obj.kind) {
        case 'circle':
            return 3.14 * obj.r ** 2
        default:
            return isAssertion(obj); // 必须实现所有逻辑
            // Argument of type 'IRant | ISquare' is not assignable to parameter of type 'never'.
            // Type 'IRant' is not assignable to type 'never'.ts(2345)
    }
}