TypeScript 的高级类型系统提供了强大的工具来创建灵活且类型安全的代码,其中映射类型(Mapped Types)和条件类型(Conditional Types)是两个极为重要的概念。本文将深入探讨这两种类型的用法和应用场景。
映射类型:转换现有类型的利器
映射类型允许我们基于现有类型创建新类型,通过遍历现有类型的属性并进行转换。
基本语法
typescript
type MappedType<T> = {
[P in keyof T]: NewType;
};
常见内置映射类型
TypeScript 提供了一些内置的映射类型:
-
Partial:使所有属性变为可选
typescripttype Partial<T> = { [P in keyof T]?: T[P]; };
-
Readonly:使所有属性变为只读
typescripttype Readonly<T> = { readonly [P in keyof T]: T[P]; };
-
Pick:从类型中选择部分属性
typescripttype Pick<T, K extends keyof T> = { [P in K]: T[P]; };
-
Record:创建具有指定键类型和值类型的类型
typescripttype Record<K extends keyof any, T> = { [P in K]: T; };
自定义映射类型示例
typescript
// 将所有属性变为可为null
type Nullable<T> = {
[P in keyof T]: T[P] | null;
};
// 为所有属性添加getter方法
type Getters<T> = {
[P in keyof T as `get${Capitalize<string & P>}`]: () => T[P];
};
条件类型:类型层面的条件判断
条件类型允许我们根据条件表达式选择不同的类型,类似于值层面的三元运算符。
基本语法
typescript
T extends U ? X : Y
常见应用
-
类型过滤
typescripttype Filter<T, U> = T extends U ? T : never;
-
提取函数返回类型
typescripttype ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
-
提取函数参数类型
typescripttype Parameters<T> = T extends (...args: infer P) => any ? P : never;
分布式条件类型
当条件类型作用于联合类型时,它会自动分布到每个联合成员上:
typescript
type Distributed = string | number extends string ? true : false; // false
type Distributed2 = (string extends string ? true : false) |
(number extends string ? true : false); // true | false → boolean
映射类型与条件类型的结合
这两种高级类型结合使用时能产生更强大的效果:
typescript
// 将类型中所有函数属性的返回类型改为Promise
type Promisify<T> = {
[P in keyof T]: T[P] extends (...args: infer A) => infer R
? (...args: A) => Promise<R>
: T[P];
};
// 移除类型中所有可选标记
type Concrete<T> = {
[P in keyof T]-?: T[P];
};
实际应用案例
- API响应类型处理
typescript
type ApiResponse<T> = {
data: T;
error: string | null;
status: number;
};
// 创建只包含数据的类型
type ResponseData<T> = ApiResponse<T>['data'];
// 创建错误处理类型
type ErrorResponse = Pick<ApiResponse<any>, 'error' | 'status'>;
- 表单验证
typescript
type Validator<T> = {
[P in keyof T]: (value: T[P]) => boolean;
};
type User = {
name: string;
age: number;
};
const userValidator: Validator<User> = {
name: (value) => value.length > 0,
age: (value) => value >= 18
};
总结
映射类型和条件类型是TypeScript类型系统中极为强大的工具,它们允许开发者:
- 基于现有类型创建新类型,减少重复代码
- 实现复杂的类型转换和操作
- 构建更加灵活和可维护的类型定义
- 在编译时捕获更多潜在错误
掌握这些高级类型技术将显著提升你的TypeScript技能,使你能够构建更加健壮和类型安全的应用程序。