首页
技术小册
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开发实战
### 18 | 高级类型(1):交叉类型与联合类型 在TypeScript的世界里,类型系统是其最强大的特性之一,它允许开发者在编译时期就捕获到许多潜在的错误,从而提升代码的质量和可维护性。随着项目复杂度的增加,基础的类型定义(如`number`、`string`、`boolean`以及接口和类类型)往往难以满足所有需求。这时,高级类型就显得尤为重要,它们为TypeScript的类型系统增添了更多的灵活性和表达能力。本章将深入探讨两种高级类型:交叉类型(Intersection Types)与联合类型(Union Types),它们是理解和使用TypeScript高级特性不可或缺的基础。 #### 交叉类型(Intersection Types) 交叉类型允许我们将多个类型合并为一个类型,这个新类型将包含所有被合并类型的特性。它使用`&`符号来定义。想象一下,你有一个用户信息的接口,同时你又希望这个用户能够拥有一些额外的权限信息。此时,交叉类型就能派上用场。 ##### 示例:用户与权限的交叉类型 首先,我们定义两个接口:`User`和`Permissions`。 ```typescript interface User { name: string; age: number; } interface Permissions { canEdit: boolean; canDelete: boolean; } ``` 现在,我们想要一个类型来表示一个既有用户信息又有权限的用户。我们可以使用交叉类型来实现这一点。 ```typescript type UserWithPermissions = User & Permissions; // 使用 const admin: UserWithPermissions = { name: "John Doe", age: 30, canEdit: true, canDelete: true }; // 错误示例:缺少canEdit属性 const regularUser: UserWithPermissions = { name: "Jane Doe", age: 25, // canEdit: false, // 缺少此行将导致编译错误 canDelete: false }; ``` 在上面的例子中,`UserWithPermissions`类型就是`User`和`Permissions`接口的交叉类型。任何被声明为`UserWithPermissions`类型的变量都必须同时满足`User`和`Permissions`接口的所有要求。 ##### 交叉类型的特性 - **属性合并**:如果两个类型中有相同的属性名但类型不同,则交叉类型中该属性的类型必须是这两个类型的兼容类型(例如,`string & number`是不合法的,但如果是两个接口有相同属性但类型可兼容,则可能合法,这通常通过类型断言或更复杂的类型关系处理)。 - **扩展性**:交叉类型可以很容易地扩展现有类型,而无需修改原始类型定义。 - **限制**:交叉类型不能包含任何重复的属性名且这些属性名对应的类型必须兼容。 #### 联合类型(Union Types) 与交叉类型相反,联合类型允许一个变量是几种类型中的任意一种。它使用`|`符号来定义。联合类型在处理可能具有多种形态的数据时非常有用,比如函数重载、可选参数等场景。 ##### 示例:数字或字符串的联合类型 ```typescript type NumberOrString = number | string; let value: NumberOrString = 42; value = "Hello, World!"; // 有效 // 访问属性时需要注意类型安全 // 错误的做法,因为不能确定value是string还是number // console.log(value.length); // TypeScript 会报错,因为number没有length属性 // 安全的做法 if (typeof value === 'string') { console.log(value.length); } ``` 在上面的例子中,`NumberOrString`是一个联合类型,它可以是`number`类型或`string`类型。当尝试访问一个联合类型变量的属性或方法时,TypeScript编译器会要求你确保当前操作是安全的,即需要通过类型守卫(如`typeof`检查、`instanceof`检查或使用自定义的类型守卫函数)来缩小类型的范围。 ##### 联合类型的特性 - **灵活性**:允许变量有多种类型,提高了代码的灵活性。 - **类型守卫**:在处理联合类型时,必须使用类型守卫来确保操作的类型安全。 - **类型推断**:在联合类型上执行操作时,TypeScript会尽可能推断出最精确的类型。 - **默认值**:在定义可能为`null`或`undefined`的联合类型时,可以很方便地处理可选值的情况。 #### 高级应用:交叉类型与联合类型的结合使用 在实际开发中,交叉类型和联合类型往往不是孤立使用的,它们经常结合在一起,以构建更复杂且表达能力更强的类型系统。 ##### 示例:带有可选权限的用户类型 ```typescript interface BaseUser { name: string; age: number; } type UserRole = 'admin' | 'editor' | 'viewer'; interface AdminPermissions { canEdit: true; canDelete: true; } interface EditorPermissions { canEdit: true; canDelete: false; } interface ViewerPermissions { canEdit: false; canDelete: false; } type UserWithRole = | (BaseUser & AdminPermissions & { role: 'admin' }) | (BaseUser & EditorPermissions & { role: 'editor' }) | (BaseUser & ViewerPermissions & { role: 'viewer' }); const user: UserWithRole = { name: "Alice", age: 28, canEdit: true, canDelete: true, role: 'admin' }; // 访问用户权限时,可以安全地根据role属性来决定 if (user.role === 'admin') { console.log(user.canEdit); // true console.log(user.canDelete); // true } ``` 在这个例子中,我们定义了一个`UserWithRole`类型,它是`BaseUser`接口与不同权限接口(`AdminPermissions`、`EditorPermissions`、`ViewerPermissions`)以及一个`role`属性的联合类型。这样的类型定义既灵活又强大,能够清晰地表达用户的角色及其对应的权限。 #### 总结 交叉类型和联合类型是TypeScript高级类型系统中的两个核心概念,它们极大地增强了TypeScript类型系统的表达能力和灵活性。通过合理使用这两种类型,我们可以构建出既安全又易于维护的代码库。在实际项目中,结合具体需求灵活运用这些高级类型,将有助于提高代码质量和开发效率。
上一篇:
17 | 类型检查机制(3):类型保护
下一篇:
19 | 高级类型(2):索引类型
该分类下的相关小册推荐:
TypeScript 全面进阶指南
剑指TypeScript
TypeScript入门指南