首页
技术小册
AIGC
面试刷题
技术文章
MAGENTO
云计算
视频课程
源码下载
PDF书籍
「涨薪秘籍」
登录
注册
01 | 重塑“类型思维”
02 | 类型基础(1):强类型与弱类型
03 | 类型基础(2):动态类型与静态类型
04 | 编写你的第一个TypeScript程序
05 | 基本类型
06 | 枚举类型
07 | 接口(1):对象类型接口
08 | 接口(2):函数类型接口
09 | 函数相关知识点梳理
10 | 类(1):继承和成员修饰符
11 | 类(2):抽象类与多态
12 | 类与接口的关系
13 | 泛型(1):泛型函数与泛型接口
14 | 泛型(2):泛型类与泛型约束
15 | 类型检查机制(1):类型推断
16 | 类型检查机制(2):类型兼容性
17 | 类型检查机制(3):类型保护
18 | 高级类型(1):交叉类型与联合类型
19 | 高级类型(2):索引类型
20 | 高级类型(3):映射类型
21 | 高级类型(4):条件类型
22 | ES6与CommonJS的模块系统
23 | 使用命名空间
24 | 理解声明合并
25 | 如何编写声明文件
26 | 配置tsconfig.json(1):文件选项
27 | 配置tsconfig.json(2):编译选项
28 | 配置tsconfig.json(3):工程引用
29 | 编译工具:从ts-loader到Babel
30 | 代码检查工具:从TSLint到ESLint
31 | 使用Jest进行单元测试
32 | 创建项目
33 | 组件与类型(1):函数组件与类组件
34 | 组件与类型(2):高阶组件与Hooks
35 | 事件处理与数据请求
36 | 列表渲染与路由
37 | Redux与类型
38 | 搭建服务端开发环境
39 | 列表的CRUD
40 | 导出Excel
41 | 搭建Vue开发环境
42 | 组件封装
43 | 组件发布
44 | 共存策略
45 | 宽松策略
46 | 严格策略
当前位置:
首页>>
技术小册>>
TypeScript开发实战
小册名称:TypeScript开发实战
### 21 | 高级类型(4):条件类型 在TypeScript的深度探索中,高级类型是不可或缺的一部分,它们极大地增强了类型系统的灵活性和表达力。条件类型(Conditional Types)作为TypeScript 2.8版本引入的一项功能,允许类型根据条件进行动态解析,为构建复杂且灵活的类型系统提供了强大的工具。本章将深入探讨条件类型的基本原理、应用场景以及高级技巧,帮助读者在TypeScript开发中更加游刃有余。 #### 一、条件类型基础 条件类型的基本语法结构类似于JavaScript中的三元运算符,但应用于类型系统。其基本形式为: ```typescript type TypeName = Condition extends TrueType ? TrueBranch : FalseBranch; ``` 这里,`Condition` 是一个待判断的类型表达式,`TrueType` 是条件成立时`Condition`应满足的类型,`TrueBranch` 是条件成立时`TypeName`的类型,而`FalseBranch`则是条件不成立时的类型。 ##### 示例:基本用法 假设我们想要根据一个类型是否为`string`来定义一个新的类型,如果是`string`,则新类型为`string`;否则,为`number`。 ```typescript type StringOrNumber = string extends any ? string : number; // 结果为 string,因为 string 总是可以赋值给 any // 更实用的例子,根据传入类型是否为 string 来决定 type IsStringType<T> = T extends string ? true : false; type Result1 = IsStringType<string>; // true type Result2 = IsStringType<number>; // false ``` #### 二、条件类型的应用场景 条件类型因其灵活性和强大的表达能力,在TypeScript中有着广泛的应用场景,包括但不限于: ##### 1. 泛型约束与类型映射 条件类型常用于增强泛型的灵活性和表达能力,通过条件判断来决定泛型参数的类型或行为。 ```typescript type ExtractKeys<T, K> = { [P in keyof T]: T[P] extends K ? P : never }[keyof T]; interface Person { name: string; age: number; isStudent: boolean; } type StringKeys = ExtractKeys<Person, string>; // 'name' ``` 在上面的例子中,`ExtractKeys`利用条件类型从`Person`接口中提取出所有值类型为`string`的键。 ##### 2. 类型安全的断言 条件类型可以用来实现类型安全的断言,避免运行时错误。 ```typescript type IsArray<T> = T extends Array<any> ? true : false; function isArray<T>(value: T): value is T & (IsArray<T> extends true ? T[] : never) { return Array.isArray(value); } // 使用 const numbers = [1, 2, 3]; if (isArray(numbers)) { // numbers 在这里被推断为 number[],无需额外断言 numbers.push(4); } ``` ##### 3. 递归类型 结合条件类型,可以实现递归类型,这在处理嵌套结构或复杂数据类型时非常有用。 ```typescript type DeepReadonly<T> = { readonly [P in keyof T]: T[P] extends object ? DeepReadonly<T[P]> : T[P]; }; interface Nested { name: string; address: { street: string; city: { name: string; population: number; }; }; } type ReadonlyNested = DeepReadonly<Nested>; ``` `DeepReadonly`类型确保`Nested`接口中的所有属性,包括嵌套对象,都被标记为只读。 #### 三、高级技巧与进阶 ##### 1. 分发条件类型 在TypeScript中,当条件类型应用于一个联合类型时,它会被“分发”到联合类型的每个成员上,这种特性称为分发条件类型(Distributive Conditional Types)。 ```typescript type ExtractString<T> = T extends string ? T : never; type T1 = ExtractString<string | number | boolean>; // string ``` 在这个例子中,`ExtractString`被应用于一个联合类型,结果是一个新的联合类型,只包含原始联合类型中满足条件的成员。 ##### 2. 推断与条件类型结合 条件类型经常与类型推断一起使用,以构建复杂的类型关系。 ```typescript type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never; function add(a: number, b: number): number { return a + b; } type AddReturnType = ReturnType<typeof add>; // number ``` 这里,`ReturnType`工具类型使用条件类型结合`infer`关键字来推断函数的返回类型。 ##### 3. 条件类型的限制与陷阱 尽管条件类型功能强大,但在使用时也需注意其潜在的限制和陷阱。例如,过度复杂的条件类型可能导致类型解析性能下降,甚至在某些情况下造成编译器崩溃。此外,条件类型的可读性也是一个挑战,过于复杂的条件表达式可能会让代码难以理解和维护。 #### 四、总结 条件类型作为TypeScript高级类型系统的一部分,极大地增强了类型表达的灵活性和能力。通过条件类型,我们可以构建出更加复杂、安全且易于维护的类型系统。然而,也需要注意其潜在的限制和陷阱,避免过度使用导致性能问题或代码可读性下降。在实际开发中,合理利用条件类型,可以显著提升TypeScript项目的质量和效率。
上一篇:
20 | 高级类型(3):映射类型
下一篇:
22 | ES6与CommonJS的模块系统
该分类下的相关小册推荐:
TypeScript入门指南
剑指TypeScript
TypeScript 全面进阶指南