跳到主要内容

条件类型

条件类型是 TypeScript 中一种高级类型,它通过在类型系统中进行条件分支,根据某个类型关系的真假来确定最终的类型。条件类型的基本语法为 T extends U ? X : Y,表示如果类型 T 可以赋值给类型 U,则结果类型为 X,否则为 Y

以下是条件类型的一些常见用法和示例:

1. 基本示例

type Check<T> = T extends string ? "string" : "non-string";

type Result = Check<number>; // "non-string"
type AnotherResult = Check<string>; // "string"

在这个例子中,Check<T> 条件类型判断 T 是否为 string 类型,如果是则为 "string",否则为 "non-string"

2. 分布式条件类型

条件类型在处理联合类型时表现得特别强大,称为分布式条件类型。当条件类型的待检查类型是一个联合类型时,条件类型会分别应用到联合类型的每个成员上,然后将结果联合起来。

type Diff<T, U> = T extends U ? never : T;
type Filter<T, U> = T extends U ? T : never;

type MyType = Diff<"a" | "b" | "c", "a" | "e">; // "b" | "c"
type MyType2 = Filter<"a" | "b" | "c", "a" | "e">; // "a"

在这个例子中,Diff 类型会过滤掉在第二个联合类型中出现的部分,而 Filter 类型则只保留在第二个联合类型中出现的部分。

3. infer 关键字

infer 关键字用于在条件类型中引入一个类型变量,并将它用于延迟推断。infer 允许我们在 extends 语句中推断类型,并在条件分支中使用这个类型。

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

function getStringLength(str: string): number {
return str.length;
}

type StringLength = ExtractReturnType<typeof getStringLength>; // number

在这个例子中,ExtractReturnType 条件类型通过 infer R 推断了函数类型 T 的返回类型,并将它应用于条件分支。

4. Exclude 和 NonNullable

TypeScript 标准库中的一些类型,比如 ExcludeNonNullable,也是通过条件类型实现的:

type Exclude<T, U> = T extends U ? never : T;
type NonNullable<T> = T extends null | undefined ? never : T;

这两个类型分别用于排除某些类型,例如 Exclude 用于从类型 T 中排除所有可以赋值给 U 的类型。

5. 条件类型的应用

条件类型常常与映射类型结合使用,实现更复杂的类型映射:

type BoxedValue<T> = { value: T };

type BoxedArray<T> = T extends any[] ? BoxedValue<T[number]> : never;

type Boxed = BoxedArray<[string, number]>; // { value: string } | { value: number }

在这个例子中,BoxedArray 条件类型会分别应用到元组的每个成员上,然后将结果联合起来。

条件类型是 TypeScript 强大而灵活的一部分,它使得我们能够根据不同的类型关系进行复杂的类型判断和映射。在实际应用中,条件类型常常用于实现更高级别的抽象和复杂的类型操作。