)
文档教程【免费下载链接】typescript-bookThe Concise TypeScript Book: A Concise Guide to Effective Development in TypeScript. Free and Open Source.项目地址https://gitcode.com/gh_mirrors/typ/typescript-book点击查看免费下载条件类型Conditional Types是 TypeScript 类型系统中根据输入类型特征做变换的核心机制而预定义条件类型则是语言内置的、开箱即用的条件类型工具集合。本文以 The Concise TypeScript Book 的对应章节为主体骨架系统讲解Exclude、Extract、NonNullable、ReturnType、Parameters、Required、Partial、Readonly共 8 个内置条件类型先厘清它们各自的语义与底层实现原理再结合仓库中的类型系统系列章节给出可复制的实战示例与组合用法。读完本文你将能够熟练使用这些工具类型在编译期完成联合类型过滤、函数签名提取、对象属性修饰符改写等常见类型变换。一、先理解基础条件类型从何而来预定义条件类型并非孤立概念它们全部建立在 TypeScript 条件类型语法之上。正如仓库中 conditional-types.md 所定义的条件类型是一种根据条件结果来决定最终类型的机制使用extends关键字加三元运算符在两种类型间做选择type 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 any[] ? true : false的含义是如果T是any[]的子类型则结果为true否则为false。可以把extends理解为子集关系T1 ⊆ T2这与 exploring-the-type-system.md 中Types as Sets类型即集合的视角一致。条件类型有两个关键特性它们是预定义条件类型行为的基石分配律Distributive当T是联合类型时条件类型会对每个联合成员分别求值再合并结果详见 distributive-conditional-types.mdtype NullableT T extends any ? T | null : never; type NumberOrBool number | boolean; type NullableNumberOrBool NullableNumberOrBool; // number | boolean | nullinfer类型推断条件类型分支中可用infer关键字提取泛型参数的具体类型详见 infer-type-inference-in-conditional-types.mdtype ElementTypeT T extends (infer U)[] ? U : never; type Numbers ElementTypenumber[]; // number type Strings ElementTypestring[]; // string正是分配律 infer这两个能力构成了Exclude、Extract、ReturnType、Parameters等预定义条件类型的实现底座。二、联合类型过滤器Exclude 与 ExtractExclude与Extract是作用在联合类型上的正反两个过滤器它们的语义在原文档中定义如下ExcludeUnionType, ExcludedType从UnionType中删除所有可赋值给ExcludedType的类型。ExtractType, Union从Union中提取所有可赋值给Type的类型。先看一个对照示例type Union a | b | c; type Excluded ExcludeUnion, a | c; // b type Extracted ExtractUnion, a | c; // a | c如果把联合类型看作集合ExcludeT, U等价于集合差集 T − UExtractT, U等价于集合交集 T ∩ U。它们的典型应用场景包括剔除事件类型中的某些分支从对象键集合中排除特定键type Keys name | age | email; type PublicKeys ExcludeKeys, email; // name | age type Falsy false | 0 | | null | undefined; type Truthy Excludeany, Falsy; // 过滤掉所有假值类型Extract的一个实用场景是从接口键中只挑出字符串键或数字键interface Article { title: string; views: number; [key: string]: unknown; } type StringKeys Extractkeyof Article, string; // string包含索引签名仓库中 type-manipulation.md 的 Utility Types 小节同样收录了Exclude与Extract的用法并给出了与a | b | c联合的相同示例可作为交叉印证。三、清理空值NonNullableNonNullableType的语义非常直接从Type中移除null和undefined。type Union a | null | undefined | b; type MyType NonNullableUnion; // a | b该类型最常见的价值在于收窄从 API、表单或第三方库传入的可能为空的数据类型。例如 React 中常见的 state 初始化写法type User { id: number; name: string }; // 初始态可能是 null但后续逻辑保证非空 const initial: User | null null; type UserState NonNullabletypeof initial; // { id: number; name: string }在实际项目中NonNullable常与可选链、判空分支搭配让类型层面与运行时空值防御形成双重保险。从实现机理看NonNullableT等价于条件类型T extends null | undefined ? never : T由于条件类型具备分配律联合类型中的每个成员都会被单独检查凡是可赋值给null | undefined的成员一律变为never最终从联合中消失——这也解释了为什么它一次能同时剔除两种空值。四、提取函数签名ReturnType 与 ParametersReturnType与Parameters是infer关键字在预定义条件类型中最典型的两处应用ReturnTypeType提取函数Type的返回值类型。ParametersType提取函数Type的参数类型列表。type Func (name: string) number; type MyType ReturnTypeFunc; // numbertype Func (a: string, b: number) void; type MyType ParametersFunc; // [a: string, b: number]注意Parameters的返回结果是元组类型tuple保留了参数顺序与可选性标记如[a: string, b?: number]。这在装饰器、高阶函数和事件处理器的类型推导中非常实用function makeRequest(url: string, options?: { timeout: number }) {} type RequestParams Parameterstypeof makeRequest; // [url: string, options?: { timeout: number } | undefined] type RequestResult ReturnTypetypeof makeRequest; // void一个真实感很强的组合场景封装一个包装函数把被包装函数的参数与返回值全部原样透传type LoggerT extends (...args: any[]) any ( ...args: ParametersT ) ReturnTypeT; const add (a: number, b: number): number a b; const loggedAdd: Loggertypeof add (a, b) { console.log(adding ${a} ${b}); return a b; // 返回值类型被保证为 number };它们的底层原理正是条件类型加inferReturnTypeT在分支中通过T extends (...args: any[]) infer R ? R : any提取RParametersT则通过T extends (...args: infer P) any ? P : never提取参数元组P。这与 infer-type-inference-in-conditional-types.md 中ElementType的写法一脉相承。五、改写对象属性Required、Partial 与 Readonly最后三个预定义条件类型作用于对象的属性修饰符本质上是映射类型Mapped Types的语法糖RequiredType将Type的所有属性变为必填。PartialType将Type的所有属性变为可选。ReadonlyType将Type的所有属性变为只读。仓库中 mapped-types.md 解释了映射类型的基本形态——用[P in keyof T]遍历对象键并逐个变换属性mapped-type-modifiers.md 则给出了三个修饰符的底层写法与这三个工具类型的实现完全对应type ReadOnlyT { readonly [P in keyof T]: T[P] }; // 等价于 ReadonlyT type MutableT { -readonly [P in keyof T]: T[P] }; // 去除 readonly type MyPartialT { [P in keyof T]?: T[P] }; // 等价于 PartialT5.1 Required全部属性转必填type Person { name?: string; age?: number; }; type A RequiredPerson; // { name: string; age: number; }典型应用是当配置对象在初始化阶段允许缺省、但在使用阶段必须完整时用Required约束后者type AppConfig { host?: string; port?: number; }; // 经过默认值合并后的配置必须是完整的 function startServer(config: RequiredAppConfig) { console.log(${config.host}:${config.port}); }RequiredT的底层实现可理解为对每个属性键应用-?修饰符{ [P in keyof T]-?: T[P] }即去除可选项标记。5.2 Partial全部属性转可选type Person { name: string; age: number; }; type A PartialPerson; // { name?: string | undefined; age?: number | undefined; }Partial最常见的用法是部分更新场景——函数的入参只需提供要修改的字段type User { id: number; name: string; email: string; }; function updateUser(id: number, patch: PartialUser) { // 调用方只需传入需要变更的字段 } updateUser(1, { name: new name }); // 合法 updateUser(1, { id: 2, email: ab.c }); // 合法注意PartialT产生的结果中可选属性会附带| undefined因此直接读取可能得到undefined需要配合判空或默认值处理。5.3 Readonly全部属性转只读type Person { name: string; age: number; }; type A ReadonlyPerson; const a: A { name: Simon, age: 17 }; a.name John; // Invalid只读属性不可赋值Readonly非常适合表达创建后不可变更的领域对象或常量配置。需要说明的是ReadonlyT是浅只读它只锁定第一层属性嵌套对象的内部属性仍可修改对于深层只读需要递归组合Readonly与索引访问类型例如type DeepReadonlyT { readonly [P in keyof T]: DeepReadonlyT[P] }。三个工具类型可以自由嵌套组合形成更强的类型约束type Point { x?: number; y?: number }; // 先补全必填再锁定只读 type ImmutablePoint ReadonlyRequiredPoint; // { readonly x: number; readonly y: number; }六、进阶组合与实战技巧6.1 用 keyof 与 Exclude 动态生成键集合把keyof取对象所有键的联合类型与Exclude/Extract组合可以在不手写字符串的前提下按条件筛选键type FormField { label: string; value: unknown; hidden?: boolean }; // 剔除可选键得到必填字段的键集合 type RequiredKeysT Excludekeyof T, keyof RequiredPickT, keyof T; type FormRequiredKeys RequiredKeysFormField; // label | valuehidden 是可选说明RequiredKeys这类高阶工具并非语言内置而是社区中常见的组合技法其可行性正建立在Exclude与Required两个内置类型的语义之上。6.2 函数工具类型的生产级用法ReturnType与Parameters在依赖注入、事件总线和插件系统里是高频工具。一个经典模式是从现有函数类型重建一个签名相同的兼容函数type Handler (event: MouseEvent) void; // 为 handler 增加日志而保持签名完全一致 const safeHandler: Handler (event) { console.log(handling, event.type); };如果第三方库没有导出某个函数的参数/返回值类型Parameterstypeof fn与ReturnTypetypeof fn可以帮你凭空提取出这些类型无需手写重复声明。6.3 在仓库中的其他章节定位它们这些预定义条件类型并非孤立知识点它们与仓库中多个章节构成完整的知识链条可交叉阅读conditional-types.md条件类型语法基础extends 三元distributive-conditional-types.md分配律如何让Exclude/Extract/NonNullable对联合逐成员生效infer-type-inference-in-conditional-types.mdReturnType/Parameters的infer实现原理mapped-types.md 与 mapped-type-modifiers.mdRequired/Partial/Readonly的映射底层type-manipulation.mdUtility Types 全集包含Record、Pick、Omit、Awaited、NoInfer等更多内置工具类型的完整示例never-type.mdnever作为空集合在条件类型分支? ... : never中的角色以及它在穷尽性检查中的应用。七、速查总表预定义条件类型语义典型底层写法典型场景ExcludeT, U从 T 中剔除可赋值给 U 的成员T extends U ? never : T联合类型过滤、键集合排除ExtractT, U从 T 中提取可赋值给 U 的成员T extends U ? T : never求交集、按条件筛选键NonNullableT从 T 中移除null与undefinedT extends null \| undefined ? never : T空值收窄、API 数据清洗ReturnTypeT提取函数 T 的返回值类型T extends (...a: any) infer R ? R : any函数返回值类型复用ParametersT提取函数 T 的参数元组T extends (...a: infer P) any ? P : never参数类型复用、函数包装RequiredT所有属性转必填{ [P in keyof T]-?: T[P] }配置完整性校验PartialT所有属性转可选{ [P in keyof T]?: T[P] }部分更新入参ReadonlyT所有属性转只读{ readonly [P in keyof T]: T[P] }不可变对象建模结语八个预定义条件类型虽然各自解决一个具体问题但它们的共同点在于全部由条件类型语法extends条件判断、分配律和infer推断三个基础能力派生而来。掌握了它们背后的机理你不仅能熟练使用这些内置工具还能以此为模板写出自己的条件类型工具——这正是 TypeScript 类型系统用类型构造类型的威力所在。建议对照仓库中的 predefined-conditional-types.md法文版或 英文版原文 原文逐条动手验证并在 IDE 中 hover 观察每个类型求值后的真实结果。赞分享文档教程【免费下载链接】typescript-bookThe Concise TypeScript Book: A Concise Guide to Effective Development in TypeScript. Free and Open Source.项目地址https://gitcode.com/gh_mirrors/typ/typescript-book点击查看免费下载相关推荐The Concise TypeScript Book深入理解预定义条件类型Predefined Conditional TypesThe Concise TypeScript Book深入理解预定义条件类型Predefined Conditional Types 预定义条件类型Pr文档教程The Concise TypeScript Book预定义条件类型Predefined Conditional Types深入解析The Concise TypeScript Book预定义条件类型Predefined Conditional Types深入解析 TypeScript文档教程The Concise TypeScript Book 精讲TypeScript 预定义条件类型Predefined Conditional Types全解析The Concise TypeScript Book 精讲TypeScript 预定义条件类型Predefined Conditional Types全文档教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考