条件类型

概述

条件类型(Conditional Types)是 TypeScript 中一种强大的类型系统特性,它允许我们根据某些条件来选择不同的类型。条件类型通常用于类型推断和类型映射,使得类型系统更加灵活和强大。

基本语法

条件类型的基本语法如下:

T extends U ? X : Y
  • T 和 U 是类型参数。
  • X 和 Y 是类型结果。
  • 如果 T 可以赋值给 U,则返回类型 X,否则返回类型 Y。

示例

示例 1: 简单的条件类型

type IsString<T> = T extends string ? true : false;

type Result1 = IsString<"hello">; // true
type Result2 = IsString<42>; // false

在这个例子中,IsString 是一个条件类型,它检查传入的类型是否为 string。如果是 string,则返回 true,否则返回 false。

示例 2: 使用条件类型进行类型推断

type ExtractArrayType<T> = T extends (infer U)[] ? U : never;

type Result3 = ExtractArrayType<number[]>; // number
type Result4 = ExtractArrayType<string[]>; // string
type Result5 = ExtractArrayType<{ key: string }[]>; // { key: string }

在这个例子中,ExtractArrayType 是一个条件类型,它使用 infer 关键字来推断数组元素的类型。如果 T 是一个数组类型,则返回数组元素的类型 U,否则返回 never。

实践练习

练习 1: 实现一个条件类型来判断是否为对象类型

type IsObject<T> = T extends object ? true : false;

type Result6 = IsObject<{ key: string }>; // true
type Result7 = IsObject<"hello">; // false

练习 2: 实现一个条件类型来提取函数的返回类型

type ExtractReturnType<T> = T extends (...args: any[]) => infer R ? R : never;

type Result8 = ExtractReturnType<() => string>; // string
type Result9 = ExtractReturnType<(x: number) => boolean>; // boolean

深入理解

分布式条件类型

当条件类型作用于一个联合类型时,它会自动分布到每个成员上。这种行为称为分布式条件类型。

type ToArray<T> = T extends any ? T[] : never;

type Result10 = ToArray<string | number>; // string[] | number[]

在这个例子中,ToArray<string | number> 会被分布为 ToArray<string> | ToArray<number>,最终结果是 string[] | number[]。

条件类型与 infer 关键字

infer 关键字用于在条件类型中推断类型。它可以出现在条件类型的 extends 子句中,用于捕获类型变量。

type Flatten<T> = T extends Array<infer U> ? U : T;

type Result11 = Flatten<number[]>; // number
type Result12 = Flatten<string>; // string

在这个例子中,Flatten 类型用于展平数组类型。如果 T 是一个数组类型,则推断出数组元素的类型 U,否则返回 T 本身。

总结

条件类型是 TypeScript 中一种非常强大的类型系统特性,它允许我们根据条件选择不同的类型。通过结合 infer 关键字,我们可以实现复杂的类型推断和类型映射。掌握条件类型将使你在 TypeScript 编程中更加得心应手。

下一步

接下来,我们将学习 TypeScript 中的映射类型和 infer 关键字,这些内容将进一步扩展你对 TypeScript 类型系统的理解。