張家港企業(yè)做網(wǎng)站seo網(wǎng)站運(yùn)營
概述
- 在 TS 中,infer 是一個高級類型操作,特別是條件類型和映射類型中非常有用的關(guān)鍵字
- 它在泛型中使用也會是一個強(qiáng)大工具,增強(qiáng)了類型推斷的能力,讓開發(fā)者更靈活地處理和操作類型
- 它允許在泛型類型推導(dǎo)過程中捕獲一個具體的類型,這對于編寫復(fù)雜的類型轉(zhuǎn)換和映射操作特別有用
- infer 的定義
- infer 表示在 extends 條件語句中以占位符出現(xiàn)的用來修飾數(shù)據(jù)類型的關(guān)鍵字
- 被修飾的數(shù)據(jù)類型等到使用時才能被推斷出來
- infer 占位符式的關(guān)鍵字出現(xiàn)的位置
- infer 出現(xiàn)在 extends 條件語句后的函數(shù)類型的參數(shù)類型位置上
- infer 出現(xiàn)在 extends 條件語句后的函數(shù)類型的返回值類型上
- infer 出現(xiàn)在類型的泛型具體化類型上
實現(xiàn)
1 )infer 出現(xiàn)在 extends 條件語句后的函數(shù)類型的參數(shù)類型位置上
// 定義了一個接口Customer,它描述了一個具有name(字符串類型)和moneyPaid(數(shù)字類型)屬性的對象
interface Customer {name: stringmoneyPaid: number
}// 定義了一個函數(shù)類型,接受一個Customer類型的參數(shù)并返回一個字符串
type custFuncType = (cust: Customer) => string// 定義了一個泛型類型inferType<T>,這是理解的重點(diǎn)。這是一個條件類型,它使用了infer關(guān)鍵字
type inferType<T> = T extends (params: infer P) => any ? P : T// 定義了inferResultType類型別名,它是通過將前面定義的custFuncType類型作為參數(shù)傳遞給inferType得到的
type inferResultType = inferType<custFuncType>
- 分析一下這行代碼:
type inferType<T> = T extends (params: infer P) => any ? P : T
T extends (params: infer P) => any
- 這部分是一個類型測試,檢查T是否可以賦值給一個函數(shù)類型
- 該函數(shù)接受一個參數(shù)(我們稱之為params)
- infer P關(guān)鍵字在這里用于聲明一個新的類型變量P,用來捕獲T中函數(shù)參數(shù)的實際類型
? P
- 如果上面的測試為真(即T確實是一個函數(shù)類型)
- 那么整個條件類型的結(jié)果就是捕獲的參數(shù)類型P
: T
- 如果上面的測試為假(即T不是函數(shù)類型或不匹配)
- 則條件類型的結(jié)果就是T本身,不做任何改變
- 最后一行代碼
type inferResultType = inferType<custFuncType>
- custFuncType是一個接受Customer類型參數(shù)的函數(shù),所以infer P會捕獲到這個參數(shù)類型
- 因此,inferResultType 實際上就是Customer類型
2 ) infer 出現(xiàn)在 extends 條件語句后的函數(shù)類型的返回值類型上
// 定義了一個接口Customer,它描述了一個具有name(字符串類型)和moneyPaid(數(shù)字類型)屬性的對象
interface Customer {custname: stringmoneyPaid: number
}
// 這個類型定義了一個函數(shù),該函數(shù)接受一個Customer類型的參數(shù)并返回一個字符串
type custFuncType = (cust: Customer) => string
type inferType<T> = T extends (params: any) => infer P ? P : T
type inferResultType = inferType<custFuncType>
- 核心在這里,
type inferType<T> = T extends (params: any) => infer P ? P : T
- 上面,
inferType
的 infer 在返回值的位置上 - infer P 表示“推斷出一個類型 P”,這個 P 是函數(shù)的返回類型
- 它根據(jù) extends 的檢查結(jié)果來選擇不同的類型
- 如果 T 是一個符合 (params: any) => … 形式的函數(shù)類型
- 那么表達(dá)式的結(jié)果是 P(即函數(shù)的返回類型)
- 否則,表達(dá)式的結(jié)果是 T 本身
- 上面,
- 最后,
type inferResultType = inferType<custFuncType>
- 由于,custFuncType 是一個返回值為 string 的函數(shù)類型
- 符合,inferType 內(nèi)部的三元推導(dǎo)的條件,因為 返回值是 P, 而在這里P又是 string 類型
- 所以,type inferResultType 就是 string 類型
3 ) infer 出現(xiàn)在類型的泛型具體化類型上
class Subject {constructor(public id: number, public name: string) {}
}const chineseSubject = new Subject(100, "語文");
const mathSubject = new Subject(101, "數(shù)學(xué)");type ElementOfSet<T> = T extends Set<infer E> ? E : never;const subjectsSet = new Set<Subject>([chineseSubject, mathSubject]);type SubjectType = ElementOfSet<typeof subjectsSet>;// 使用推斷出的SubjectType類型
function printSubject(subject: SubjectType) {console.log(`學(xué)科ID: ${subject.id}, 學(xué)科名稱: ${subject.name}`);
}printSubject(chineseSubject);
- 核心代碼在這里:
type ElementOfSet<T> = T extends Set<infer E> ? E : never;
- 如果 參數(shù) T 屬于 Set 類型,則 ElementOfSet 則是 E 的類型
- 這里
Set<infer E>
使用 infer E 推導(dǎo)出 E的類型,如果符合 extends 條件,則返回E,否則返回 never
const subjectsSet = new Set<Subject>([chineseSubject, mathSubject]);
- 這里
subjectsSet
是一個 Set 類型,而且單個元素是Subject
類型
- 這里
type SubjectType = ElementOfSet<typeof subjectsSet>;
ElementOfSet<typeof subjectsSet>
這里符合內(nèi)部條件,所以,它最終是一個Subject
類型
- 所以,在最后,
printSubject
中完美運(yùn)行
總結(jié)
- infer關(guān)鍵字在TypeScript中為泛型編程提供了一個強(qiáng)大的工具
- 它不僅增強(qiáng)了類型系統(tǒng)的表達(dá)能力,還使開發(fā)者能夠編寫出更加靈活和精確的類型定義
- 通過掌握infer的使用,你能夠在處理復(fù)雜類型邏輯和類型轉(zhuǎn)換時更加游刃有余
- 提升代碼的類型安全性和可維護(hù)性