类型守卫

62 阅读1分钟

typeof

在类型上下文中获取变量或属性的类型

// 获取变量和对象类型
  interface UserInfo {
    name: string;
    age: number;
  }
  let userInfo: UserInfo = {
    name: 'name1',
    age: 1
  }
  type user = typeof userInfo; // 等同于UserInfo
  type age = typeof userInfo.age; // number

  //只读属性
  let list: readonly number[] = [0,1]
  type Type = typeof list // readonly number[]

  // 获取函数类型
  function getInfo(name: string, age: number): number {
    return age + 1
  } 
  type GetInfo = typeof getInfo // (name: string, age: number) => number
  // 没有显式的描述函数返回类型, typeof会推断返回类型

  // 获取enum类型
  enum example {
    one,
    two,
    three = '3'
  }
  type result = typeof example // {one: number, two: number, three: string}

  // 获取class
  class User {
    name: string;
    age: number;
    constructor(name: string, age: number) {}
  }
  type UserClass = typeof User // new (name: string, age: number) => User

配合ReturnType

  function user() {
    return {name: 'name', age: 1}
  }
  // type Type = ReturnType<user>
  // 报错,user是值而不是类型
  type Type = ReturnType<typeof user>

配合keyof

  const user = {
    name: 'name',
    age: 1,
  };

  type User = keyof typeof user; // 'name' | 'age'

instanceof

内置类型守卫,用于检查一个值是否是给定构造函数或类的实例

interface Accessory {
    brand: string;
  }
  // implements
  // 实现,一个新的类,从父类或者接口实现所有的属性和方法,同时可以重写属性和方法,包含一些新的功能
  // 一个类通过关键字implements声明自己使用一个或者多个接口。
  class Necklace implements Accessory{
    kind: string;
    brand: string;
    constructor(brand: string, kind: string) {    
      this.brand = brand;
      this.kind = kind;
    }
  }
  class bracelet implements Accessory{
    brand: string;
    year: number;
    constructor(brand: string, year: number) {    
      this.brand = brand;
      this.year = year;
    }
  }
  const getRandomAccessory = () =>{
    return Math.random() < 0.5 ?
      new bracelet('cartier', 2021) :
      new Necklace('choker', 'TASAKI');
  }
  let Accessory = getRandomAccessory();
  if (Accessory instanceof bracelet) {
    console.log(Accessory.year);  // 2021
  }
  if (Accessory instanceof Necklace) {
    console.log(Accessory.brand);  // 'TASAKI'   
  }

in

检查对象是否具有特定属性,返回一个布尔值,表示属性是否在对象中,使用该属性区分不同类型

const user = {
  name: 'xx',
  age: 0
}
console.log('name' in user) // true

type User = 'name' | 'age'
type users = {
  [key in User] : string
}

字面量相等判断

  • ==
  • ===
  • !=
  • !==
type Foo = 'foo' | 'bar' | 'unknown'

function test(value: Foo) {
  if (value !== 'unknown') {
    // value 类型收紧为'foo' | 'bar'
  } 
}

//判断条件不是直接通过字面量书写,而是通过一个条件函数时,类型守卫会失效
function isString(value: any) {
  return typeof value === 'string'
}

function foo(value: string | number) {
  if (isString(value)) {
   // isString没有生效,value 类型仍为 string | number
  }
}

自定义类型保护 类型谓词 is

type A = {
  id: number,
  name: string
}
type B = {
  id: number,
  age: number
}
type C = A | B
const isA = (param: C): param is A => {
  return param.id === 0
} 
// 验证是否是number类型 
function isNumber(x: any): x is number { 
  return typeof x === "number"; 
}