Typescript中的自定义守卫和VUE3源码中的范例

在Vue3 关于ref的源码中有这样一段代码

export function isRef(r: any): r is Ref {
  return !!(r && r.__v_isRef === true)
}

源码地址:
https://github.com/vuejs/core/blob/main/packages/reactivity/src/ref.ts#L62

这样的 r is Ref就是自定义守卫,一般在ts中我们,我们判断类型,可以用:

  1. 类型判断:typeof
  2. 实例判断:instanceof
  3. 属性判断:in
  4. 字面量相等判断:==, ===, !=, !==

举个例子:

type Person = {
  name: string
  age?: number
}

// 获得所有age属性
function getPersonAges(persons: Person[]): number[] {
  return persons.filter(person => person.age !== undefined).map(person => person.age)
}

但是上面的代码会报错:

Type '(number | undefined)[]' is not assignable to type 'number[]'.
Type 'number | undefined' is not assignable to type 'number'.
Type 'undefined' is not assignable to type 'number'.

因为Person[]数组还是接收了Person类型,我们看filter()源码,会发现这样一个重载函数

filter(predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[];
    /**
     * Returns the elements of an array that meet the condition specified in a callback function.
     * @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.
     * @param thisArg An object to which the this keyword can refer in the predicate function. If thisArg is omitted, undefined is used as the this value.
     */

所以上面的代码可以这样写:

type Person = {
  name: string
  age?: number
}

type FullPerson = Required

function getPersonAges(persons: Person[]): number[] {
  return persons
    .filter((person): person is FullPerson => person.age !== undefined)
    .map(person => person.age);
}

这样经过filter处理后得到的结果类型为FullPerson[],到达map对FullPerson类型的数据取值age就能得到我们想要的number类型数据了。


这里的type FullPerson = Required是typescript提供的一种全局通用方法,

  1. Partial将类型属性都设置为可选,
  2. 文中提到的 Required,和Partial 相反,将类型属性都设置为必须
  3. readonly, 将类型属性设置成Readonly
    等等

你可能感兴趣的:(Typescript中的自定义守卫和VUE3源码中的范例)