元素码农
基础
UML建模
数据结构
算法
设计模式
网络
TCP/IP协议
HTTPS安全机制
WebSocket实时通信
数据库
sqlite
postgresql
clickhouse
后端
rust
go
java
php
mysql
redis
mongodb
etcd
nats
zincsearch
前端
浏览器
javascript
typescript
vue3
react
游戏
unity
unreal
C++
C#
Lua
App
android
ios
flutter
react-native
安全
Web安全
测试
软件测试
自动化测试 - Playwright
人工智能
Python
langChain
langGraph
运维
linux
docker
工具
git
svn
🌞
🌙
目录
▶
TypeScript环境准备
安装与配置
第一个TS程序
编译流程解析
▶
基础类型系统
类型注解语法
原始类型定义
数组与元组
接口与对象
▶
高级类型系统
泛型编程
条件类型
映射类型
类型推断
类型保护
高级类型工具
▶
函数开发
函数类型声明
可选参数与默认值
箭头函数应用
函数重载
泛型函数
▶
类与面向对象
类的定义
继承与修饰符
存取器使用
抽象类与接口
泛型类与抽象类
访问修饰符与属性
▶
模块化开发
模块导入导出
类型声明文件
命名空间
模块解析策略
▶
工程实践
tsconfig详解
常见编译选项
项目构建配置
代码组织最佳实践
单元测试
调试技巧
▶
常见问题
类型错误处理
类型断言技巧
类型兼容性
版本迁移指南
发布时间:
2025-03-31 09:40
↑
☰
# 类型保护 类型保护是TypeScript中的一种特性,它可以在特定的代码块中缩小类型的范围。本文将详细介绍TypeScript中的类型保护机制及其应用。 ## 什么是类型保护? 类型保护是一些表达式,它们在编译时会执行类型检查。通过使用类型保护,我们可以告诉编译器某个变量的具体类型,从而安全地访问该类型特有的属性和方法。 ## typeof类型保护 `typeof`是最基本的类型保护方式: ```typescript function padLeft(value: string | number, padding: string | number) { if (typeof padding === "number") { // 这里TypeScript知道padding是number类型 return " ".repeat(padding) + value; } if (typeof padding === "string") { // 这里TypeScript知道padding是string类型 return padding + value; } throw new Error(`Expected string or number, got '${padding}'`); } ``` ## instanceof类型保护 `instanceof`用于检查一个对象是否是某个类的实例: ```typescript class Bird { fly() { console.log("flying..."); } } class Fish { swim() { console.log("swimming..."); } } function move(pet: Bird | Fish) { if (pet instanceof Bird) { // 这里TypeScript知道pet是Bird类型 pet.fly(); } else { // 这里TypeScript知道pet是Fish类型 pet.swim(); } } ``` ## in操作符类型保护 `in`操作符可以安全地检查一个对象是否具有某个属性: ```typescript interface Bird { fly(): void; layEggs(): void; } interface Fish { swim(): void; layEggs(): void; } function move(pet: Bird | Fish) { if ("fly" in pet) { // 这里TypeScript知道pet是Bird类型 pet.fly(); } else { // 这里TypeScript知道pet是Fish类型 pet.swim(); } } ``` ## 自定义类型保护 我们可以定义自己的类型保护函数: ```typescript interface Rectangle { kind: "rectangle"; width: number; height: number; } interface Circle { kind: "circle"; radius: number; } type Shape = Rectangle | Circle; // 自定义类型保护函数 function isRectangle(shape: Shape): shape is Rectangle { return shape.kind === "rectangle"; } function calculateArea(shape: Shape) { if (isRectangle(shape)) { // 这里TypeScript知道shape是Rectangle类型 return shape.width * shape.height; } else { // 这里TypeScript知道shape是Circle类型 return Math.PI * shape.radius ** 2; } } ``` ## 可辨识联合类型 可辨识联合是TypeScript中的一种高级模式,它结合了联合类型、字面量类型和类型保护: ```typescript interface Square { kind: "square"; size: number; } interface Rectangle { kind: "rectangle"; width: number; height: number; } interface Circle { kind: "circle"; radius: number; } type Shape = Square | Rectangle | Circle; function area(s: Shape) { switch (s.kind) { case "square": return s.size * s.size; case "rectangle": return s.width * s.height; case "circle": return Math.PI * s.radius ** 2; default: // 确保处理了所有可能的情况 const _exhaustiveCheck: never = s; return _exhaustiveCheck; } } ``` ## 类型保护的最佳实践 1. **优先使用内置类型保护**: - 使用`typeof`检查原始类型 - 使用`instanceof`检查类实例 - 使用`in`检查属性存在性 2. **使用可辨识联合**: - 为每个类型添加一个字面量类型的标签 - 使用switch语句进行类型区分 - 使用never类型确保完整性检查 3. **自定义类型保护函数**: - 函数返回类型使用`parameterName is Type`格式 - 函数名应该清晰地表明其用途 - 保持函数的纯粹性,避免副作用 ## 实际应用场景 ### 1. 错误处理 ```typescript interface Success<T> { kind: "success"; data: T; } interface Error { kind: "error"; message: string; } type Result<T> = Success<T> | Error; function handleResult<T>(result: Result<T>) { if (result.kind === "success") { // 处理成功情况 console.log(result.data); } else { // 处理错误情况 console.error(result.message); } } ``` ### 2. API响应处理 ```typescript interface User { id: number; name: string; } interface ApiResponse<T> { status: number; data?: T; error?: string; } function isSuccessResponse<T>(response: ApiResponse<T>): response is ApiResponse<T> & { data: T } { return response.status === 200 && response.data !== undefined; } async function fetchUser(id: number) { const response: ApiResponse<User> = await fetch(`/api/users/${id}`).then(r => r.json()); if (isSuccessResponse(response)) { // 安全地访问response.data return response.data; } else { throw new Error(response.error || "Unknown error"); } } ``` ### 3. 事件处理 ```typescript type MouseEvent = { kind: "mouse"; x: number; y: number; }; type KeyboardEvent = { kind: "keyboard"; key: string; }; type Event = MouseEvent | KeyboardEvent; function handleEvent(event: Event) { switch (event.kind) { case "mouse": console.log(`Mouse at (${event.x}, ${event.y})`); break; case "keyboard": console.log(`Key pressed: ${event.key}`); break; } } ``` ## 总结 类型保护是TypeScript中非常重要的特性,它允许我们: - 在运行时安全地处理不同类型的值 - 通过多种方式缩小类型范围 - 创建类型安全的代码分支 - 实现更好的代码组织和错误处理 合理使用类型保护可以帮助我们编写更加健壮和可维护的代码。通过组合使用不同的类型保护方式,我们可以处理各种复杂的类型场景,同时保持代码的类型安全性。