TypeScript 条件类型(Conditional Types)是一种高级类型工具,允许基于一个条件来选择两种不同的类型之一。条件类型的使用通常结合泛型类型参数,能够在类型系统中进行复杂的条件分支操作。条件类型的通用形式如下:
typescript
T extends U ? X : Y
T
是待检查的类型。U
是要检查是否可分配给T
的类型。- 如果
T
可以赋值给U
,则条件类型的结果是X
,否则是Y
。
1、可选属性的条件类型
考虑一个使用条件类型来创建可选属性的示例:
typescript
type MakePropertyOptional<T, K extends keyof T> = {
[P in K]: T[P];
} & {
[P in Exclude<keyof T, K>]?: T[P];
};
type OriginalType = {
name: string;
age: number;
};
type UpdatedType = MakePropertyOptional<OriginalType, 'age'>;
定义了一个条件类型 MakePropertyOptional
,它接受两个类型参数:T
是原始类型,K
是属性名的联合类型。它的工作原理如下:
MakePropertyOptional<OriginalType, 'age'>
将OriginalType
的属性按照K
的分组分为两部分,一部分包括age
属性,另一部分包括其余属性。age
属性保持不变,而其他属性被标记为可选(?
)。
2、联合类型的条件类型
考虑一个使用条件类型来过滤联合类型的示例:
typescript
type FilterByType<T, U> = T extends U ? T : never;
type OriginalUnion = string | number | boolean;
type FilteredUnion = FilterByType<OriginalUnion, string>;
在这个示例中,FilterByType
条件类型将筛选出 OriginalUnion
联合类型中的符合条件的类型。在这里,我们只选择了字符串类型,所以 FilteredUnion
的类型将是 string
。
3、根据条件选择返回类型
这个示例演示了如何使用条件类型根据条件选择返回类型:
typescript
type If<Condition extends boolean, Then, Else> = Condition extends true ? Then : Else;
type Result = If<true, 'Yes', 'No'>; // Result 类型为 'Yes'
If
是一个自定义条件类型,它根据 Condition
参数的值返回 Then
或 Else
中的一个。在这里,由于条件是 true
,所以 Result
的类型是 'Yes'
。
这些示例展示了 TypeScript 条件类型的多种应用,包括属性操作、类型过滤和条件分支。它们允许你在类型级别进行复杂的判断和操作,提高了代码的类型安全性和可读性。 当使用 TypeScript 的条件类型时,你可以执行许多复杂的类型操作。以下是更多示例,每个示例都详细描述其目的和工作原理:
4、从对象类型中提取特定属性类型
假设你有一个包含不同属性类型的对象,并且你想从中提取特定属性的类型。你可以使用条件类型来实现这一点:
typescript
type ExtractPropertyType<T, K> = T extends { [key: string]: infer U } ? U : never;
type MyObject = {
name: string;
age: number;
isValid: boolean;
};
type AgeType = ExtractPropertyType<MyObject, 'age'>; // AgeType 类型为 number
在这个示例中,ExtractPropertyType
条件类型根据属性名 K
从对象类型 T
中提取对应属性的类型。
5、根据条件从联合类型中排除特定类型
有时你可能想从联合类型中排除特定的类型。条件类型可以帮助你实现这一点:
typescript
type ExcludeType<T, U> = T extends U ? never : T;
type OriginalUnion = string | number | boolean;
type WithoutNumbers = ExcludeType<OriginalUnion, number>;
在这个示例中,ExcludeType
条件类型将从 OriginalUnion
联合类型中排除了 number
类型,所以 WithoutNumbers
的类型将是 string | boolean
。
6、根据数组元素类型构建新数组类型
你可以使用条件类型来构建新数组类型,其中的每个元素类型都是给定类型的属性类型:
typescript
type ArrayElementType<T> = T extends (infer U)[] ? U : never;
type MyArray = [string, number, boolean];
type Element = ArrayElementType<MyArray>; // Element 类型为 string | number | boolean
在这个示例中,ArrayElementType
条件类型将从数组类型 T
中提取元素类型,这对于操作数组类型非常有用。
7、使用条件类型进行函数参数检查
条件类型可以用于检查函数的参数类型,并根据不同的条件执行不同的操作:
typescript
type CheckParams<T> = T extends (...args: infer Args) => any
? Args
: never;
function printLength(arr: number[]) {
const length = arr.length;
console.log(`Array length: ${length}`);
}
type Params = CheckParams<typeof printLength>; // Params 类型为 [number[]]
在这个示例中,CheckParams
条件类型从函数类型 T
中提取参数类型。这可以用来在编译时检查函数的参数类型。
这些示例展示了 TypeScript 条件类型的更多应用,包括属性提取、类型排除、数组操作和函数参数检查。条件类型可以帮助你在类型级别执行复杂的操作,从而增强代码的类型安全性和可维护性。