typescript高级工具类型通过泛型、映射类型、条件类型和类型推断组合,解决业务中类型随逻辑动态变化的问题,如字段按需提取、响应结构智能过滤、promise内层类型提取及表单验证类型自动推导。

TypeScript 高级工具类型不是为了炫技,而是为了解决真实业务中“类型随逻辑动态变化”的问题。比如商品数据在列表页、详情页、购物车页字段需求不同;表单校验规则由配置生成,错误对象结构需自动推导;API 响应根据参数开关字段,类型不能硬编码。这时候靠 interface 或基础联合/交叉类型已经不够——得用泛型 + 映射类型 + 条件类型 + 类型推断,组合出可复用、可推导、可约束的类型“函数”。
用映射类型做字段级控制
映射类型是构建工具类型的基础,核心是 keyof T 遍历键 + [P in ...] 重构每个属性。它让“批量修改字段特性”变得可声明、可复用。
-
只读 + 深度递归:适合 DTO 层冻结数据,避免误改
type DeepReadonly<t> = T extends object ? { readonly [P in keyof T]: DeepReadonly<t> } : T;</t></t> -
按需提取 + 重命名:对接后端返回的驼峰/下划线字段时很实用
type CamelToSnake<t> = { [K in keyof T as K extends string ? `${Lowercase<k>}_` : K]: T[K] };</k></t> -
结合条件类型做智能过滤:比如只保留字符串字段用于搜索
type StringKeys<t in keyof t extends string k : never>type StringOnly<t pick stringkeys>>;</t></t>
用条件类型实现类型分支逻辑
条件类型 T extends U ? X : Y 是类型层面的 if-else。它不运行时判断,而是在编译期根据类型兼容性做静态推导,特别适合处理“输入类型决定输出形状”的场景。
-
区分响应结构:后端统一返回
{ code: number; data?: any; msg?: string },但你希望code === 0时data是具体类型,否则是nevertype ApiResponse<t code: number extends infer c data: t : data never>(实际中常配合自定义类型守卫或包装函数)</t> -
自动推导函数返回值:封装一个通用请求函数,传入接口就自动获得对应响应类型
declare function request<t>(url: string): Promise<t>;<br>type GetProductRes = Awaited<returntype request id: number name: string>>>;</returntype></t></t>
-
联合类型的精准缩小:比如
status是'idle' | 'loading' | 'success' | 'error',你想写个工具类型,把'idle'和'loading'归为 loading 状态组type LoadingStatus = 'idle' | 'loading';<br>type IsLoading<s s extends loadingstatus true : false></s>
用泛型约束 + infer 提取深层结构
泛型提供参数化能力,infer 则让它能“解构”复杂类型。二者结合,才能从函数、Promise、数组甚至嵌套对象里精准捞出你关心的部分。
-
提取 Promise 内部类型(内置
Awaited就是这么来的)type UnwrapPromise<t t extends promise r> ? R : T;</t> -
从函数签名中抽参数和返回值
type ParametersOf<f f extends infer a> any ? A : never;<br>type ReturnTypeOf<f f extends any> infer R ? R : never;</f></f>
-
处理多层嵌套 API 响应:假设后端返回
{ result: { data: { items: Product[] } } },你不想每次手动写res.result.data.items的类型type DeepPick<t p extends string> = P extends `${infer L}.${infer R}` ? L extends keyof T ? DeepPick<t r> : never : never : P extends keyof T ? T[P] : never;</t></t>
调用DeepPick<apiresponse></apiresponse>直接得到Product[]
组合成业务就绪的工具类型
真正落地时,高级类型要像函数一样“组合使用”。比如动态表单验证:
- 先定义规则类型:
type Rule = { required?: boolean; maxLength?: number; pattern?: RegExp }; - 再用映射类型生成校验结果结构:
type ValidationResult<t in keyof t string undefined></t> - 最后用泛型+条件类型关联字段与规则:
type FormRules<t in keyof t rule>function validate<t>(data: T, rules: FormRules<t validationresult> { /* 实现 */ }</t></t></t> - IDE 能自动提示每个字段该填什么规则,调用后返回的错误对象也严格对应字段名——全部静态可推导,无需运行时猜测
不复杂但容易忽略:工具类型写完要加单元测试(用 type Expect<t u> = T extends U ? (U extends T ? true : false) : false;</t> 这类断言),也要配合 JSDoc 注释说明输入输出,否则团队协作时没人敢改。










