在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中我们,我们判断类型,可以用:
- 类型判断:typeof
- 实例判断:instanceof
- 属性判断:in
- 字面量相等判断:==, ===, !=, !==
举个例子:
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<S extends T>(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<Person>
function getPersonAges(persons: Person[]): number[] {
return persons
.filter<FullPerson>((person): person is FullPerson => person.age !== undefined)
.map(person => person.age);
}
这样经过filter处理后得到的结果类型为FullPerson[],到达map对FullPerson类型的数据取值age就能得到我们想要的number类型数据了。
这里的type FullPerson = Required<Person>
是typescript提供的一种全局通用方法,
-
Partial<Type>
将类型属性都设置为可选, - 文中提到的
Required<Type>
,和Partial 相反,将类型属性都设置为必须 -
readonly<Type>
, 将类型属性设置成Readonly
等等