TypeScript类型体操实用技巧:5个必会套路

2026-03-29 0 437

一、核心速查:5个最实用的类型体操模式

以下是 类型编程中最常用、最能解决实际问题的 5 个技巧。直接对照使用,无需翻阅文档。

技巧 适用场景 核心代码
1. 键值映射( Types) 批量修改对象属性类型 type <T> = { [P in keyof T]: T[P] }
2. 条件类型( Types) 根据输入类型动态输出 type <T> = T ? true : false
3. 模板字面量类型 拼接字符串字面量类型 type = Hello ${}
4. 递归类型 处理嵌套结构或数组 type <T> = { [P in keyof T]: <T[P]> }
5. 类型推断(infer) 从复杂类型中提取部分 type <T> = T (...args: any[]) => infer R ? R : never

二、详细实战:每个技巧的完整用法

技巧1:键值映射( Types)

标准写法(参考 官方内置工具类型):

type <T> = {
  [P in keyof T]?: T[P]
}

常见变体

添加 { [P in keyof T]: T[P] }

过滤属性:{ [P in keyof T as P _${} ? never : P]: T[P] }(剔除下划线开头的键)

修改值类型:{ [P in keyof T]: T[P] ? : T[P] }

实战案例:将接口中所有 Date 类型转为字符串

type <T> = {
  [K in keyof T]: T[K]  Date ?  : T[K]
}
 User {
  name: 
  birth: Date
}
type  = <User> // { name: ; birth:  }

技巧2:条件类型( Types)

基础语法T U ? X : Y

分布式条件类型(当 T 是联合类型时自动分发):

type <T> = T  any ? T[] : never
type  = < | > // [] | [],不是 (|)[]

常见应用

排除 null/:type <T> = T null | ? never : T

提取函数参数:type <T> = T (...args: infer P) => any ? P : never

官方定义参考: 手册中 <T, U> 的实现

type <T, U> = T  U ? never : T

技巧3:模板字面量类型( Types)

能力:在类型层面拼接字符串,配合 infer 可以解析字符串。

基础

type  = on${&lt;&gt;} // "" | "" 等
type  = Hello, ${}!        // 所有以 Hello, 开头、! 结尾的字符串

解析字符串(使用 infer):

type <Url  > = 
  Url  ${infer }://${infer Rest} 
    ? { : ; rest: Rest } 
    : never
type  = <";> 
// { : "https"; rest: "" }

实战:类型安全的 CSS 单位

type Unit = "px" | "em" | "rem"
type <U  Unit> = ${}${U}
type Width = <"px"> // "10px" | "20px" 等所有带 px 的数字字符串

技巧4:递归类型( Types)

重要限制: 递归深度默认上限约 1000 层,超出会报错 Type is deep

标准模式

type <T> = {
   [P in keyof T]: <T[P]>
}

处理数组和元组

type <T> = T   (infer U)[]
  ?  <U>[]
  : <T>

实战:展平嵌套数组():

type <T> = T  any[] 
  ? T[]  infer U 
    ? U  any[] 
      ? <U> 
      : U
    : never
  : T
type Flat = <[1, [2, [3]]]> // 1 | 2 | 3

类型体操实用技巧

技巧5:类型推断(infer

只能在条件类型的 子句中使用

提取数组元素类型

type <T> = T  (infer U)[] ? U : never
type Item = <[]> // 

提取 内部类型(类似内置 <T>):

type <T> = T  <infer U> ? <U> : T
type  = <<<>>> // 

提取函数返回值(内置 <T> 简化版):

type <T> = T  (...args: any[]) => infer R ? R : never

提取函数参数元组(内置 <T>):

type <T> = T  (...args: infer P) => any ? P : never

三、常见错误与解决方案

错误信息 原因 解决方案
Type is deep and 递归类型超出深度限制或无终止条件 增加基础条件(如 T never ? never);重构为非递归
find name 'infer' 在条件类型外部使用 infer 确保 infer 只在 T ... ? infer X ... 内部
Type 'T' is not to type '' 模板字面量类型要求传入字符串字面量 使用 T 约束或 as const 断言
分布式条件类型产生意外联合类型 未用 [] 包裹泛型参数 [T] [U] 代替 T U 关闭分发

四、练习与验证

在线验证工具 (官方,可设置 : true

自测题(答案见文末):

1. 实现 Pick<T, K>(从 T 中选取 K 键)

2. 实现 Omit<T, K>(从 T 中排除 K 键)

3. 实现 <T, U, V>(给对象 T 添加键 U,类型 V)

4. 实现 <T>(递归地将所有属性变为可选)

答案

// 1. Pick
type <T, K  keyof T> = { [P in K]: T[P] }
// 2. Omit (基于 Pick 和 )
type <T, K  keyof T> = Pick<T, <keyof T, K>>
// 3. 
type <T, U  , V> = T & { [P in U]: V }
// 4. 
type <T> = {
  [P in keyof T]?: T[P]   ? <T[P]> : T[P]
}

五、权威参考资料

官方文档:Type

内置工具类型源码:lib.es5.d.ts(随 安装)

社区标准:type-(类型体操题库,遵循官方行为)

申明:本文由第三方发布,内容仅代表作者观点,与本网站无关。对本文以及其中全部或者部分内容的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。本网发布或转载文章出于传递更多信息之目的,并不意味着赞同其观点或证实其描述,也不代表本网对其真实性负责。

七爪网 行业资讯 TypeScript类型体操实用技巧:5个必会套路 https://www.7claw.com/2827159.html

七爪网源码交易平台

相关文章