条件类型(Conditional Types)是 TypeScript 中的一种高级类型,它允许你根据条件表达式来选择类型。条件类型的语法类似于三元运算符,可以根据某个类型的条件来决定最终的类型。条件类型通常与泛型一起使用,用于创建更灵活和复杂的类型。
条件类型的基本语法
条件类型的语法如下:
T extends U ? X : Y
其中:
T
是一个类型参数。
U
是一个类型或类型表达式。
X
和 Y
是类型表达式。
如果 T
可以赋值给 U
,则条件类型的结果为 X
,否则为 Y
。
示例
以下是一个简单的条件类型示例,展示了如何根据类型参数 T
是否为 string
类型来选择不同的类型:
type IsString<T> = T extends string ? true : false;
type A = IsString<"hello">; // true
type B = IsString<42>; // false
在这个例子中,IsString
是一个条件类型,它根据 T
是否为 string
类型来选择 true
或 false
。
条件类型的常见用法
1. 类型过滤
条件类型可以用于过滤类型,例如从联合类型中提取特定类型的成员:
type FilterString<T> = T extends string ? T : never;
type C = FilterString<"hello" | 42 | "world">; // "hello" | "world"
在这个例子中,FilterString
条件类型从联合类型 "hello" | 42 | "world"
中过滤出 string
类型的成员,结果为 "hello" | "world"
。
2. 类型映射
条件类型可以用于映射类型,例如将联合类型中的每个成员映射为另一种类型:
type ToArray<T> = T extends any ? T[] : never;
type D = ToArray<string | number>; // string[] | number[]
在这个例子中,ToArray
条件类型将联合类型 string | number
中的每个成员映射为数组类型,结果为 string[] | number[]
。
3. 递归条件类型
条件类型可以递归使用,用于处理嵌套的类型结构:
type Flatten<T> = T extends Array<infer U> ? Flatten<U> : T;
type E = Flatten<Array<Array<number>>>; // number
在这个例子中,Flatten
条件类型递归地将嵌套的数组类型展平,最终结果为 number
。
4. 分布式条件类型
当条件类型作用于联合类型时,它会自动分布到联合类型的每个成员上:
type Distributed<T> = T extends any ? T[] : never;
type F = Distributed<string | number>; // string[] | number[]
在这个例子中,Distributed
条件类型作用于联合类型 string | number
时,会自动分布到每个成员上,结果为 string[] | number[]
。
条件类型的实际应用
1. 提取函数返回类型
条件类型可以用于提取函数的返回类型:
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
function greet(): string {
return "Hello, world!";
}
type G = ReturnType<typeof greet>; // string
在这个例子中,ReturnType
条件类型提取了 greet
函数的返回类型 string
。
2. 提取 Promise 的解析类型
条件类型可以用于提取 Promise
的解析类型:
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
type H = UnwrapPromise<Promise<string>>; // string
在这个例子中,UnwrapPromise
条件类型提取了 Promise<string>
的解析类型 string
。
总结
条件类型是 TypeScript 中用于根据条件表达式选择类型的高级特性。它通常与泛型一起使用,用于创建更灵活和复杂的类型。条件类型可以用于类型过滤、类型映射、递归类型处理等场景,帮助开发者编写出更强大和类型安全的代码。理解条件类型的使用场景和语法,可以帮助你更好地利用 TypeScript 的类型系统。