条件类型
条件类型是 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 标准库中的一些类型,比如 Exclude
和 NonNullable
,也是通过条件类型实现的:
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 强大而灵活的一部分,它使得我们能够根据不同的类型关系进行复杂的类型判断和映射。在实际应用中,条件类型常常用于实现更高级别的抽象和复杂的类型操作。