元素码农
基础
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:38
↑
☰
# 条件类型 条件类型是TypeScript中的一个强大特性,它允许我们根据类型关系来选择不同的类型。本文将详细介绍条件类型的使用方法和应用场景。 ## 条件类型基础 条件类型的语法类似于JavaScript中的三元运算符,但是作用于类型而不是值: ```typescript type Check<T> = T extends string ? 'string' : 'not string'; // 使用示例 type A = Check<string>; // 类型为 'string' type B = Check<number>; // 类型为 'not string' ``` ## 分配条件类型 当条件类型用于泛型类型时,如果传入的类型是联合类型,条件类型会被分配到联合类型的每个成员: ```typescript type ToArray<T> = T extends any ? T[] : never; type StrNumArr = ToArray<string | number>; // 等价于: string[] | number[] ``` ## infer关键字 `infer`关键字允许我们在条件类型中推断类型,并在true分支中引用该类型: ```typescript type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any; function foo() { return 42; } type FooReturn = ReturnType<typeof foo>; // 类型为 number ``` ## 实用的条件类型 ### 1. 提取Promise的值类型 ```typescript type UnwrapPromise<T> = T extends Promise<infer U> ? U : T; type Result = UnwrapPromise<Promise<string>>; // 类型为 string type NoPromise = UnwrapPromise<number>; // 类型为 number ``` ### 2. 提取函数参数类型 ```typescript type Parameters<T> = T extends (...args: infer P) => any ? P : never; function greet(name: string, age: number) { return `${name} is ${age} years old`; } type GreetParams = Parameters<typeof greet>; // 类型为 [string, number] ``` ### 3. 移除类型中的null和undefined ```typescript type NonNullable<T> = T extends null | undefined ? never : T; type Type = string | null | undefined | number; type NonNullableType = NonNullable<Type>; // 类型为 string | number ``` ## 条件类型与映射类型结合 条件类型可以与映射类型结合使用,创建更复杂的类型转换: ```typescript type PickByType<T, U> = { [P in keyof T]: T[P] extends U ? P : never }[keyof T]; interface Person { name: string; age: number; address: string; } type StringKeys = PickByType<Person, string>; // 类型为 "name" | "address" ``` ## 实际应用场景 ### 1. API响应类型处理 ```typescript type ApiResponse<T> = { success: true; data: T; error: null; } | { success: false; data: null; error: string; }; function handleResponse<T>(response: ApiResponse<T>) { if (response.success) { // TypeScript知道这里的response.data类型为T console.log(response.data); } else { // TypeScript知道这里的response.error类型为string console.error(response.error); } } ``` ### 2. 类型安全的事件处理 ```typescript type EventMap = { click: MouseEvent; keypress: KeyboardEvent; load: Event; }; function handleEvent<K extends keyof EventMap>( event: K, handler: (e: EventMap[K]) => void ) { // 类型安全的事件处理 } // 正确的用法 handleEvent('click', (e) => { /* e 的类型是 MouseEvent */ }); handleEvent('keypress', (e) => { /* e 的类型是 KeyboardEvent */ }); ``` ### 3. 类型安全的状态更新 ```typescript type State = { user: { name: string; age: number } | null; posts: string[]; loading: boolean; }; type Action<K extends keyof State> = { type: K; payload: State[K]; }; function updateState<K extends keyof State>( state: State, action: Action<K> ): State { return { ...state, [action.type]: action.payload }; } ``` ## 最佳实践 1. **保持简单**:条件类型可能变得非常复杂,尽量保持类型定义简单明了。 2. **适当使用类型注释**:在复杂的条件类型中,使用中间类型别名来提高可读性: ```typescript type IsString<T> = T extends string ? true : false; type IsNumber<T> = T extends number ? true : false; type IsBoolean<T> = T extends boolean ? true : false; type Primitive<T> = IsString<T> extends true ? 'string' : IsNumber<T> extends true ? 'number' : IsBoolean<T> extends true ? 'boolean' : 'other'; ``` 3. **避免过度使用**:不是所有类型关系都需要用条件类型来表达,有时使用联合类型或交叉类型更简单。 ## 总结 条件类型是TypeScript类型系统中的一个强大工具,它允许我们: - 基于类型关系进行类型选择 - 使用infer关键字进行类型推断 - 创建复杂的类型转换 - 实现类型安全的程序设计 合理使用条件类型可以帮助我们构建更加类型安全和可维护的代码。但要注意避免过度复杂化,保持代码的可读性和可维护性。