TypeScript 分布式条件类型
TypeScript 的条件类型(Conditional Types)是一种强大的工具,它允许我们根据输入类型动态地选择输出类型。而分布式条件类型(Distributive Conditional Types)是条件类型的一种特殊行为,它在处理联合类型时会自动分发到每个成员上。本文将详细介绍分布式条件类型的概念、工作原理以及实际应用。
什么是分布式条件类型?
分布式条件类型是 TypeScript 中条件类型的一种特性。当条件类型作用于联合类型时,TypeScript 会将条件类型分发到联合类型的每个成员上,然后再将结果组合成一个新的联合类型。
简单来说,如果你有一个联合类型 A | B | C
,并且对它应用条件类型 T extends U ? X : Y
,TypeScript 会分别对 A
、B
和 C
进行判断,最终得到 (A extends U ? X : Y) | (B extends U ? X : Y) | (C extends U ? X : Y)
。
代码示例
type IsString<T> = T extends string ? true : false;
type Result1 = IsString<"hello">; // true
type Result2 = IsString<42>; // false
type Result3 = IsString<"hello" | 42>; // true | false
在上面的例子中,Result3
的类型是 true | false
,因为 TypeScript 将 IsString
分发到了联合类型 "hello" | 42
的每个成员上。
分布式条件类型的工作原理
为了更好地理解分布式条件类型的工作原理,我们可以将其分解为以下几个步骤:
- 分发:当条件类型作用于联合类型时,TypeScript 会将条件类型分发到联合类型的每个成员上。
- 判断:对每个成员进行条件判断。
- 组合:将每个成员的结果组合成一个新的联合类型。
示例解析
type ToArray<T> = T extends any ? T[] : never;
type Result = ToArray<string | number>; // string[] | number[]
在这个例子中,ToArray
是一个条件类型,它接受一个类型 T
,并返回 T[]
。当 T
是联合类型 string | number
时,TypeScript 会将其分发为:
string extends any ? string[] : never
→string[]
number extends any ? number[] : never
→number[]
最终,Result
的类型是 string[] | number[]
。
分布式条件类型仅在条件类型中的 T
是裸类型参数(即没有被包装在其他类型中)时生效。如果 T
被包装在其他类型中(如 [T]
),则不会发生分发。
实际应用场景
分布式条件类型在实际开发中有许多应用场景,尤其是在处理复杂类型时。以下是一些常见的应用场景:
1. 过滤联合类型
我们可以使用分布式条件类型来过滤联合类型中的某些成员。例如,过滤掉联合类型中的 null
和 undefined
:
type NonNullable<T> = T extends null | undefined ? never : T;
type Result = NonNullable<string | number | null | undefined>; // string | number
在这个例子中,NonNullable
类型会过滤掉 null
和 undefined
,最终得到 string | number
。
2. 提取特定类型的成员
我们可以使用分布式条件类型来提取联合类型中符合特定条件的成员。例如,提取所有函数类型:
type ExtractFunction<T> = T extends (...args: any[]) => any ? T : never;
type Result = ExtractFunction<string | (() => void) | number>; // () => void
在这个例子中,ExtractFunction
类型会提取出联合类型中的所有函数类型。
3. 映射联合类型
分布式条件类型还可以用于对联合类型进行映射。例如,将联合类型中的每个成员转换为数组类型:
type ToArray<T> = T extends any ? T[] : never;
type Result = ToArray<string | number>; // string[] | number[]
在这个例子中,ToArray
类型会将联合类型中的每个成员转换为数组类型。
总结
分布式条件类型是 TypeScript 中一个非常强大的特性,它允许我们在处理联合类型时自动分发条件类型到每个成员上。通过理解其工作原理,我们可以更好地利用这一特性来处理复杂的类型逻辑。
在实际开发中,分布式条件类型常用于过滤、提取和映射联合类型。掌握这一特性将帮助你编写更加灵活和强大的类型定义。
附加资源与练习
- TypeScript 官方文档:Conditional Types
- 练习:尝试编写一个类型工具
ExtractStrings<T>
,从联合类型T
中提取所有字符串类型的成员。
type ExtractStrings<T> = T extends string ? T : never;
type Result = ExtractStrings<string | number | boolean | "hello">; // "hello" | string
通过练习,你将更好地理解分布式条件类型的工作原理和应用场景。