条件类型(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 的类型系统。