在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
就是自定義守衛(wèi),一般在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[]
數(shù)組還是接收了Person
類型卓研,我們看filter()
源碼窘问,會發(fā)現(xiàn)這樣一個重載函數(shù)
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類型的數(shù)據(jù)取值age就能得到我們想要的number類型數(shù)據(jù)了家凯。
這里的type FullPerson = Required<Person>
是typescript提供的一種全局通用方法疗疟,
-
Partial<Type>
將類型屬性都設置為可選程帕, - 文中提到的
Required<Type>
住练,和Partial 相反,將類型屬性都設置為必須 -
readonly<Type>
愁拭, 將類型屬性設置成Readonly
等等