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