定義條件類型(Predefined Conditional Types)實(shí)用指南)
文檔教程【免費(fèi)下載鏈接】typescript-bookThe Concise TypeScript Book: A Concise Guide to Effective Development in TypeScript. Free and Open Source.項(xiàng)目地址https://gitcode.com/gh_mirrors/typ/typescript-book點(diǎn)擊查看免費(fèi)下載預(yù)定義條件類型是 TypeScript 內(nèi)置的、基于條件類型機(jī)制封裝而成的一組合用工具類型用于根據(jù)給定類型的特征自動(dòng)完成常見類型轉(zhuǎn)換。本文以 The Concise TypeScript Book目錄總覽中Predefined Conditional Types章節(jié)為核心骨架逐一拆解Exclude、Extract、NonNullable、ReturnType、Parameters、Required、Partial、Readonly的語義、使用邊界與源碼級(jí)原理并結(jié)合倉庫中 conditional-types.md、infer-type-inference-in-conditional-types.md、mapped-type-modifiers.md 等相關(guān)章節(jié)與 type-manipulation.md 的 Utility Types 清單做縱深擴(kuò)展。讀完本文你將能夠熟練在業(yè)務(wù)代碼與類型庫中正確選用這 8 個(gè)內(nèi)置條件類型并理解其底層實(shí)現(xiàn)方式。從條件類型到預(yù)定義條件類型預(yù)定義條件類型Predefined Conditional Types在 TypeScript 官方術(shù)語體系中屬于內(nèi)置條件類型——即語言自帶、由編譯器實(shí)現(xiàn)的一組類型轉(zhuǎn)換工具。它們并非獨(dú)立的語法特性而是建立在條件類型基礎(chǔ)之上的預(yù)制件。條件類型Conditional Types用extends關(guān)鍵字加三元表達(dá)式根據(jù)條件在兩個(gè)類型之間二選一見 conditional-types.mdtype IsArrayT T extends any[] ? true : false; const myArray [1, 2, 3]; const myNumber 42; type IsMyArrayAnArray IsArraytypeof myArray; // Type true type IsMyNumberAnArray IsArraytypeof myNumber; // Type false其中能賦值給誰的判斷T extends U本質(zhì)上是在問T的所有取值是否都能賦給U所描述的集合。這一集合論視角在本書 exploring-the-type-system.md 的 Types as Sets 一節(jié)有系統(tǒng)闡述。在此基礎(chǔ)上TypeScript 用infer關(guān)鍵字在條件類型中反向提取泛型參數(shù)的真實(shí)類型見 infer-type-inference-in-conditional-types.mdtype ElementTypeT T extends (infer U)[] ? U : never; type Numbers ElementTypenumber[]; // number type Strings ElementTypestring[]; // string預(yù)定義條件類型正是條件類型 infer 分配律distributive conditional types的工程化組合。本書 distributive-conditional-types.md 章節(jié)詳細(xì)討論了分配條件類型的行為理解它能幫你判斷Exclude/Extract等工具在聯(lián)合類型上逐成員展開時(shí)為何會(huì)產(chǎn)生精確結(jié)果。聯(lián)合類型篩選Exclude 與 ExtractExcludeUnionType, ExcludedType從Type中移除所有可賦值給ExcludedType的類型刪除聯(lián)合類型中的指定成員。type Union a | b | c; type MyType ExcludeUnion, a | c; // b官方簽名是ExcludeT, U T extends U ? never : T。由于條件類型在裸類型參數(shù)naked type parameter上具有分配性T中的每個(gè)聯(lián)合成員都會(huì)被單獨(dú)代入判斷能賦給U的成員被替換為never參與聯(lián)合時(shí)自動(dòng)消融其余成員保留最終得到差集。這在 type-manipulation.md 的 Utility Types 一節(jié)中有同款示例ExcludeUnion, a | c結(jié)果為b。ExtractType, Union從Union中提取出所有可賦值給Type的類型篩選出聯(lián)合類型中的指定成員。type Union a | b | c; type MyType ExtractUnion, a | c; // a | c官方簽名是ExtractT, U T extends U ? T : never。它與Exclude是互補(bǔ)關(guān)系Extract保留交集成員Exclude刪除交集成員兩者常配合使用例如從全部事件名中剔除已處理事件名得到待處理事件名??煽招郧謇鞱onNullableType從Type中移除null和undefined。type Union a | null | undefined | b; type MyType NonNullableUnion; // a | b官方簽名是NonNullableT T {}現(xiàn)代版本或NonNullableT T extends null | undefined ? never : T早期版本。無論采用哪種實(shí)現(xiàn)其效果都是把null/undefined從聯(lián)合中剔除。它與編譯器選項(xiàng)strictNullChecks直接相關(guān)當(dāng)開啟該選項(xiàng)后本書 strictnullchecks.md 有專門章節(jié)變量只能顯式聲明為null | undefined聯(lián)合時(shí)才允許接收空值而NonNullable正是處理這類可能為空類型的最常用工具。例如從 DOM 查詢或配置讀取得到string | null時(shí)用NonNullableT即可得到純string。函數(shù)類型解剖ReturnType 與 ParametersReturnTypeType提取函數(shù)Type的返回類型。type Func (name: string) number; type MyType ReturnTypeFunc; // number官方簽名為ReturnTypeT T extends (...args: any[]) infer R ? R : any。它利用infer R從函數(shù)類型中提取返回值。該能力的背景是 TypeScript 的返回類型推斷見 type-from-func-return.md編譯器能根據(jù)函數(shù)實(shí)現(xiàn)自動(dòng)推斷返回類型而ReturnType則把這個(gè)已經(jīng)推斷出的返回類型從函數(shù)類型中顯式取出常用于讓一個(gè)函數(shù)的結(jié)果類型與另一個(gè)函數(shù)保持同步避免重復(fù)聲明。ParametersType提取函數(shù)Type的參數(shù)類型以元組形式返回。type Func (a: string, b: number) void; type MyType ParametersFunc; // [a: string, b: number]官方簽名為ParametersT T extends (...args: infer P) any ? P : never。返回結(jié)果是帶標(biāo)簽的元組類型[a: string, b: number]標(biāo)簽即原參數(shù)的名稱關(guān)于具名元組可參考 named-tuple-type-labeled.md。典型用途包括用Parameterstypeof fn直接得到某函數(shù)的參數(shù)列表配合Omit、Partial生成改造版參數(shù)類型或在事件系統(tǒng)里把回調(diào)參數(shù)分發(fā)給其他函數(shù)。屬性形態(tài)變換Required、Partial 與 Readonly這三者均屬于映射類型Mapped Types家族見 mapped-types.md通過[P in keyof T]遍歷已有類型的每個(gè)屬性并施加變換。本書 mapped-type-modifiers.md 一節(jié)明確列出了三種修飾符readonly/readonly使屬性只讀、-readonly使屬性可變、?使屬性可選。RequiredType將Type的所有屬性變?yōu)楸匦枰瞥蛇x的?。type Person { name?: string; age?: number; }; type A RequiredPerson; // { name: string; age: number; }官方簽名為RequiredT { [P in keyof T]-?: T[P] }其中的-?修飾符把可選標(biāo)記?顯式移除從而保證所有屬性非可選。常用于把部分更新請(qǐng)求體強(qiáng)轉(zhuǎn)為完整實(shí)體或在表單校驗(yàn)完成后把可能缺失的字段收緊為必定存在。PartialType將Type的所有屬性變?yōu)榭蛇x。type Person { name: string; age: number; }; type A PartialPerson; // { name?: string | undefined; age?: number | undefined; }官方簽名為PartialT { [P in keyof T]?: T[P] }使用?修飾符標(biāo)記每個(gè)屬性為可選。注意結(jié)果類型中每個(gè)可選屬性被推斷為string | undefined/number | undefined這正是 strictnullchecks.md 所描述的行為。它最經(jīng)典的實(shí)戰(zhàn)場(chǎng)景是更新接口接受PartialEntity讓調(diào)用方只傳需要修改的字段。ReadonlyType將Type的所有屬性變?yōu)橹蛔x。type Person { name: string; age: number; }; type A ReadonlyPerson; const a: A { name: Simon, age: 17 }; a.name John; // Invalid官方簽名為ReadonlyT { readonly [P in keyof T]: T[P] }用readonly修飾符標(biāo)記每個(gè)屬性。只讀是編譯期約束對(duì)a.name的賦值會(huì)直接產(chǎn)生編譯錯(cuò)誤但編譯后的 JavaScript 中屬性仍然可變因此它適合表達(dá)領(lǐng)域?qū)ο髣?chuàng)建后不應(yīng)被修改的不變量而非運(yùn)行時(shí)安全手段。若要逆向解除只讀可結(jié)合-readonly自定義MutableT見 mapped-type-modifiers.md 示例。組合實(shí)戰(zhàn)用預(yù)定義條件類型解決真實(shí)問題以下三個(gè)模式展示了將上述工具組合使用的典型場(chǎng)景可對(duì)照 type-manipulation.md 中 Utility Types 清單繼續(xù)擴(kuò)展// 1. 回調(diào)參數(shù)直接復(fù)用無需手寫參數(shù)類型 type MyHandler (id: number, message: string) void; type MyHandlerParams ParametersMyHandler; // [id: number, message: string] // 2. 把外部可能為空的結(jié)果收窄為安全類型 type ApiResponse string | null | undefined; type SafeResponse NonNullableApiResponse; // string // 3. 從事件聯(lián)合中精確篩選需要處理的事件 type AllEvents click | input | scroll | focus; type HandledEvents ExtractAllEvents, click | input; // click | input type RemainingEvents ExcludeAllEvents, HandledEvents; // scroll | focus再結(jié)合ReturnType實(shí)現(xiàn)類型跟隨函數(shù)const fetchUser async (): Promise{ id: number; name: string } { // 實(shí)現(xiàn)省略返回類型由實(shí)現(xiàn)自動(dòng)推斷 return { id: 1, name: Simon }; }; type User ReturnTypetypeof fetchUser; // Promise{ id: number; name: string } type UserData AwaitedUser; // { id: number; name: string }遞歸解開 Promise這里AwaitedT見 type-manipulation.md 的AwaitedT小節(jié)負(fù)責(zé)遞歸解開 Promise 嵌套與ReturnType配合即可從任意異步函數(shù)無痛導(dǎo)出其返回的數(shù)據(jù)類型。原理與驗(yàn)證在編譯器中印證你的理解如果想親手驗(yàn)證上述類型結(jié)果可以使用本倉庫 tools/tsconfig.json 中啟用的嚴(yán)格編譯環(huán)境strict: true、target: es2022、lib: [es2022, ...]cd tools npx tsc --noEmit your-check.ts # 借助 strict 模式驗(yàn)證類型推斷通過故意制造錯(cuò)誤賦值例如給Exclude得到的b類型賦a或?qū)eadonly類型屬性賦值tsc會(huì)給出與上文注釋一致的類型錯(cuò)誤信息從而反向驗(yàn)證每個(gè)內(nèi)置條件類型的精確輸出。這是把類型即文檔落到實(shí)操的推薦路徑類型系統(tǒng)本身會(huì)替你把使用邊界檢查清楚。小結(jié)預(yù)定義條件類型一句話語義底層實(shí)現(xiàn)要點(diǎn)ExcludeT, U從T中刪除可賦給U的成員T extends U ? never : T依賴分配條件類型ExtractT, U從T中提取可賦給U的成員T extends U ? T : never依賴分配條件類型NonNullableT移除null與undefinedT {}或T extends null \| undefined ? never : TReturnTypeT提取函數(shù)返回類型T extends (...args: any[]) infer R ? R : anyParametersT提取函數(shù)參數(shù)元組T extends (...args: infer P) any ? P : neverRequiredT全部屬性變?yōu)楸匦鑬 [P in keyof T]-?: T[P] }映射類型PartialT全部屬性變?yōu)榭蛇x{ [P in keyof T]?: T[P] }映射類型ReadonlyT全部屬性變?yōu)橹蛔x{ readonly [P in keyof T]: T[P] }映射類型這 8 個(gè)預(yù)定義條件類型覆蓋了聯(lián)合類型篩選、可空性清理、函數(shù)類型解剖與對(duì)象屬性形態(tài)變換四大類日常需求是 TypeScript 類型編程的標(biāo)準(zhǔn)庫。深入掌握它們?cè)俳Y(jié)合本書 conditional-types.md、infer-type-inference-in-conditional-types.md、mapped-types.md 與 type-manipulation.md 等章節(jié)你就能在此基礎(chǔ)上自行封裝自定義條件類型寫出更精確、更可復(fù)用的類型體系。贊分享文檔教程【免費(fèi)下載鏈接】typescript-bookThe Concise TypeScript Book: A Concise Guide to Effective Development in TypeScript. Free and Open Source.項(xiàng)目地址https://gitcode.com/gh_mirrors/typ/typescript-book點(diǎn)擊查看免費(fèi)下載相關(guān)推薦The Concise TypeScript Book 精講TypeScript 預(yù)定義條件類型Predefined Conditional Types全解析The Concise TypeScript Book 精講TypeScript 預(yù)定義條件類型Predefined Conditional Types全文檔教程The Concise TypeScript Book 精講TypeScript 預(yù)定義條件型Predefined Conditional Types完整指南The Concise TypeScript Book 精講TypeScript 預(yù)定義條件型Predefined Conditional Types完整文檔教程The Concise TypeScript Book深入理解預(yù)定義條件類型Predefined Conditional TypesThe Concise TypeScript Book深入理解預(yù)定義條件類型Predefined Conditional Types 預(yù)定義條件類型Pr文檔教程上一篇postgres_lsp 規(guī)則詳解requireConcurrentIndexDeletion —— 用 DROP INDEX CONCURRENTLY 避免刪除索引時(shí)鎖表阻塞生產(chǎn)讀寫下一篇SQLite數(shù)據(jù)庫集成指南使用Sequelize輕松管理本地?cái)?shù)據(jù)存儲(chǔ)創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考