尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

深入理解 TypeScript 分布式条件类型:联合类型逐成员转换实战(The Concise TypeScript Book)

发布时间:2026/9/25 2:17:31

资讯中心
01
ARTICLE

深入理解 TypeScript 分布式条件类型:联合类型逐成员转换实战(The Concise TypeScript Book)

深入理解 TypeScript 分布式条件类型:联合类型逐成员转换实战(The Concise TypeScript Book)
文档教程【免费下载链接】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点击查看免费下载分布式条件类型Distributive Conditional Types是 TypeScript 条件类型体系中最具威力的特性之一它让一个条件类型自动展开应用到联合类型的每一个成员上从而用一行类型定义完成批量转换。本文以 The Concise TypeScript Book英文原版章节及其印尼语译本为骨架深入讲解分配机制的触发条件、关闭方法以及与映射类型、内置预定义条件类型的联动实战帮助你彻底掌握这一类型层面的批处理能力。什么是分布式条件类型分布式条件类型是一种允许类型分布在联合类型上的特性它会对联合类型的每一个成员单独应用类型转换而不是把整个联合当作一个整体来处理。当使用映射类型mapped type或高阶类型higher-order type时这一特性尤其有用。这是 distributive-conditional-types.md 给出的原始示例type NullableT T extends any ? T | null : never; type NumberOrBool number | boolean; type NullableNumberOrBool NullableNumberOrBool; // number | boolean | null这里NullableNumberOrBool的结果是number | boolean | null而不是(number | boolean) | null这种看起来等价但语义不同的写法。关键在于条件类型并没有把number | boolean作为整体去判断extends any而是分别对number和boolean求值再把结果合并回一个联合类型。要理解它需要先回顾两个基础概念联合类型用|表示一个值可以是多种类型之一例如string | number见 union-type.md条件类型用extends关键字配合三元运算符根据类型关系在两种结果类型之间二选一见 conditional-types.md。分布式条件类型就是这两者碰撞出的化学反应。核心机制裸类型参数才会触发分配分配行为并非无条件发生。TypeScript 的规则是只有当被检查的类型即extends左侧的类型是一个裸naked的泛型类型参数时条件类型才会在联合的每个成员上分别求值。所谓裸类型参数是指类型参数直接出现在extends左侧没有被[]、Promise、T[]之类的结构包裹。回看上面的示例逐成员展开的完整过程如下对成员numbernumber extends any ? number | null : never→ 结果为number | null对成员booleanboolean extends any ? boolean | null : never→ 结果为boolean | null合并两个结果(number | null) | (boolean | null)number | boolean | null。这一步一步的分发就是分布distribute二字的由来。如果T恰好是单个类型如Nullablenumber则与普通条件类型无异直接返回number | null。如何关闭分配非裸参数与元组包裹并不是所有场景都需要分配行为。当你希望把整个联合类型当作一个整体来判断时分配反而会带来错误结果。TypeScript 提供了两种典型的关闭手段。非裸类型参数天然关闭分配只要被检查的类型被某种结构包裹就不再触发分配。例如// T[] 包裹不分配整个联合作为一个整体判断 type IsArrayT T extends any[] ? true : false; type R1 IsArraynumber | string[]; // false因为 number | string[] 整体不 extends any[] // 元组包裹 [T]不分配 type NotDistributedT [T] extends [any] ? yes : no; // PromiseT 包裹不分配 type UnwrapDistT PromiseT extends Promiseinfer U ? U : never;用元组包裹实现整体判断当泛型参数本身是裸的、但又想强制按整体判断时最常见的惯用法是把两侧都包进元组type IsUnionT [T] extends [never] ? false : ...;更实用的场景是从联合中取出可赋值类型时避免误分配。比如定义仅当 T 恰好是 string 的子集时才成立的判断type ExactlyStringT [T] extends [string] ? (string extends T ? true : false) : false; type A ExactlyStringstring; // true type B ExactlyStringhello; // falsehello 可赋给 string 但反之不行 type C ExactlyStringstring | number; // false元组包裹[T] extends [U]让T不再裸奔分配被关闭条件判断退化为普通的整体关系判断。分配机制与内置预定义条件类型的关系分配语义最著名的应用是 TypeScript 内置的预定义条件类型见 predefined-conditional-types.md。其中Exclude、Extract、NonNullable正是依赖分配行为才能生效的// 相当于内置 Exclude 的实现T extends U ? never : T // 对联合 T 的每个成员逐一判断丢弃能赋给 U 的成员 type MyExcludeT, U T extends U ? never : T; // 相当于内置 Extract 的实现保留能赋给 U 的成员 type MyExtractT, U T extends U ? T : never; // 相当于内置 NonNullable 的实现去掉 null 与 undefined type MyNonNullableT T extends null | undefined ? never : T; type Result MyExcludea | b | c, a; // b | c type Result2 MyExtracta | b | c, a | b; // a | b type Result3 MyNonNullablestring | null | undefined; // string如果Exclude不是分布式的a | b | c extends a整体判断会直接得到never——正是分配机制让这些工具类型具备了过滤联合成员的能力。这与本文开头NullableT的逐成员变换是同一套底层语义。实战场景用分布式条件类型构建类型工具场景一为联合的每个成员追加可空性这是文档原示例的直接应用——批量让联合中每个类型都可为空type NullableT T extends any ? T | null : never; type Status idle | loading | success | error; type NullableStatus NullableStatus; // idle | null | loading | null | success | null | error | null // 去重合并后即: idle | loading | success | error | null注意联合类型会自动合并相同成员因此null只出现一次。场景二过滤出联合中特定形状的成员结合infer见 infer-type-inference-in-conditional-types.md可以从联合中提取出所有函数成员type ExtractFunctionT T extends (...args: any[]) any ? T : never; type Mixed | ((x: number) string) | { kind: data; value: number } | (() void); type OnlyFunctions ExtractFunctionMixed; // ((x: number) string) | (() void)分配机制保证每个成员都被单独送入extends (...args: any[]) any判断非函数成员被替换为never而联合中never会被自动消除。场景三与映射类型协作原文档特别指出分配特性在使用映射类型或高阶类型时尤其有用。一个典型组合是逐成员包装type ApiResultT T extends any ? { value: T; ok: true } | { ok: false } : never; type User { id: number; name: string }; type ApiResponse ApiResultUser | { id: number }; // 分别对 User 与 { id: number } 生成包装结果再合并成联合这样写出的高阶类型可以一次性为一个联合中的所有成员生成对应的包装形态这正是类型层面批处理的价值所在。本章在全书中的位置与延伸阅读在 The Concise TypeScript Book 的目录结构中本章sidebarorder: 41位于条件类型基础conditional-types.mdorder 40之后紧随其后的是infer类型推断infer-type-inference-in-conditional-types.mdorder 42与预定义条件类型predefined-conditional-types.mdorder 43三者共同构成完整的条件类型知识链想掌握extends条件判断的入门语法读 条件类型章节想用infer从结构里抽取类型参数读 infer 章节想直接使用Exclude/Extract/NonNullable等内置工具读 预定义条件类型章节本书还提供了多语言版本例如与本文对应的印尼语译本和中文译本便于对照学习。小结分布式条件类型是 TypeScript 类型系统中组合爆炸的源头之一也是编写通用类型工具的核心武器。回顾要点触发条件extends左侧是裸泛型类型参数时条件类型会在联合的每个成员上分别求值逐成员变换每个成员独立进入条件判断结果再合并回联合关闭方法用[T]、T[]、PromiseT等结构包裹被检查类型即可关闭分配经典应用NullableT、ExcludeT, U、ExtractT, U、NonNullableT等工具类型都依赖这一语义。掌握了它你就能像写循环一样在类型层面批量处理联合成员写出更简洁、更通用、更易维护的类型工具。赞分享文档教程【免费下载链接】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 中分布条件类型Distributive Conditional Types详解让转换逐个作用于联合类型的每个成员The Concise TypeScript Book 中分布条件类型Distributive Conditional Types详解让转换逐个作用于联合文档教程The Concise TypeScript Book 精读分配条件类型Distributive Conditional Types——让联合类型逐成员变换的类型级 mapThe Concise TypeScript Book 精读分配条件类型Distributive Conditional Types——让联合类型逐成员变文档教程The Concise TypeScript Book 实战深入理解条件类型中的 infer 类型推断The Concise TypeScript Book 实战深入理解条件类型中的 infer 类型推断 导读 infer 是 TypeScript 条件类型文档教程上一篇Motionity滤镜特效终极指南亮度、对比度、饱和度等10种调整技巧下一篇如何快速掌握 DevSpaceKubernetes 开发终极指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。