首页
技术小册
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开发实战
### 第17章 类型检查机制(3):类型保护 在TypeScript的开发旅程中,类型检查是确保代码质量、提高可维护性和可读性的关键一环。随着项目规模的扩大和复杂度的提升,我们不可避免地会遇到需要处理多种类型数据的场景。在这些情况下,TypeScript的类型系统提供了强大的工具来帮助我们安全地处理类型,而类型保护(Type Guards)就是其中的佼佼者。本章将深入探讨类型保护的概念、原理及其在实战中的应用。 #### 1. 类型保护概述 类型保护是TypeScript中一种特殊的表达式,它允许开发者在运行时检查一个值的类型,从而确保在编译时能够安全地访问该值的特定属性或调用其方法,即使这些属性或方法在其他类型上可能不存在。通过类型保护,我们可以在不牺牲类型安全性的前提下,编写出更加灵活和强大的代码。 类型保护主要分为两种形式:用户自定义的类型保护和TypeScript内置的类型保护。用户自定义类型保护通常通过类型谓词(Type Predicates)实现,而内置类型保护则包括`typeof`类型保护、`instanceof`类型保护、`in`关键字类型保护以及通过`is`操作符的类型保护(如`Array.isArray`)。 #### 2. 用户自定义类型保护 用户自定义类型保护是TypeScript中一个非常强大的特性,它允许我们根据特定的逻辑条件来断言一个值的类型。这通常通过给函数添加一个返回值为布尔值的类型谓词来实现,该类型谓词会明确指定当函数返回`true`时,传入参数的类型。 ##### 示例:判断字符串是否为数字类型 ```typescript function isNumericString(value: any): value is string { return typeof value === 'string' && !isNaN(Number(value)) && !/^\s*$/.test(value); } // 使用 const input = "123"; if (isNumericString(input)) { console.log(input.length); // 编译通过,因为此时TypeScript认为input是string类型 } ``` 在这个例子中,`isNumericString`函数是一个类型保护,它接受任意类型的`value`作为参数,并返回一个布尔值。该函数的类型谓词`value is string`告诉TypeScript,如果函数返回`true`,那么`value`就一定是一个字符串。这使得我们可以在`if`语句内部安全地访问`input.length`属性。 #### 3. TypeScript内置类型保护 ##### 3.1 `typeof` 类型保护 `typeof`操作符在TypeScript中不仅可以用来在运行时判断一个值的类型,还可以结合类型保护在编译时提供更严格的类型检查。 ```typescript function isString(value: any): value is string { return typeof value === 'string'; } // 使用 const x = 123; if (isString(x)) { // 这里TypeScript会报错,因为x不可能是string console.log(x.toUpperCase()); } ``` ##### 3.2 `instanceof` 类型保护 `instanceof`操作符用于检测一个构造函数的`prototype`属性是否出现在某个实例对象的原型链上。在TypeScript中,它可以用来作为类型保护,以确认一个对象是否是某个类的实例。 ```typescript class Animal { move() { console.log('Animal moves'); } } class Dog extends Animal { bark() { console.log('Dog barks'); } } function isDog(a: Animal): a is Dog { return a instanceof Dog; } const myDog: Animal = new Dog(); if (isDog(myDog)) { myDog.bark(); // 编译通过,因为TypeScript认为myDog是Dog类型 } ``` ##### 3.3 `in` 关键字类型保护 `in`关键字可以用来检查对象上是否存在某个属性,虽然它本身不直接作为类型保护使用,但可以通过结合逻辑判断来间接实现类型保护的效果。 ```typescript interface Square { kind: "square"; size: number; } interface Circle { kind: "circle"; radius: number; } type Shape = Square | Circle; function getArea(shape: Shape): number { if ("size" in shape) { // 这里TypeScript推断shape为Square类型 return shape.size * shape.size; } else if ("radius" in shape) { // 这里TypeScript推断shape为Circle类型 return Math.PI * shape.radius * shape.radius; } throw new Error("Unknown shape"); } ``` #### 4. 高级类型保护:类型断言与类型守卫的组合 在实际开发中,我们往往会将类型断言(Type Assertions)与类型保护结合使用,以处理那些TypeScript无法直接推断的类型信息。类型断言允许我们手动告诉TypeScript一个值的类型是什么,但这是一种相对危险的操作,因为它绕过了TypeScript的类型检查系统。因此,在使用类型断言之前,最好先用类型保护来确保类型的正确性。 ##### 示例:处理联合类型中的可选属性 ```typescript interface Person { name: string; age?: number; } interface Employee extends Person { id: number; role: string; } type PersonOrEmployee = Person | Employee; function getInfo(person: PersonOrEmployee): string { if ("id" in person) { // 通过类型保护,我们知道person一定是Employee类型 return `Employee ${person.name} has ID ${person.id}`; } else { // 如果没有id属性,则默认使用Person类型 return `Person ${person.name}${person.age ? `, ${person.age} years old` : ''}`; } } // 假设我们有以下数据 const emp: Employee = { name: "Alice", id: 1, role: "Engineer", age: 30 }; const psn: Person = { name: "Bob" }; console.log(getInfo(emp)); // 输出: Employee Alice has ID 1 console.log(getInfo(psn)); // 输出: Person Bob ``` #### 5. 结论 类型保护是TypeScript中一个非常强大的特性,它允许我们在运行时根据值的类型来安全地访问其属性或方法,同时保持编译时的类型安全。通过用户自定义类型保护和TypeScript内置的类型保护(如`typeof`、`instanceof`、`in`关键字),我们可以编写出既灵活又健壮的代码。在实际开发中,合理运用类型保护可以显著提升代码的可读性和可维护性,减少运行时错误的发生。希望本章内容能帮助你更好地理解和应用TypeScript的类型保护机制。
上一篇:
16 | 类型检查机制(2):类型兼容性
下一篇:
18 | 高级类型(1):交叉类型与联合类型
该分类下的相关小册推荐:
TypeScript入门指南
TypeScript 全面进阶指南
剑指TypeScript