TypeScript 类型体操:从初学者到进阶高手的必经之路

1 阅读1分钟

目录 (Outline)


一、类型体操的核心工具箱

要玩转类型体操,你必须熟练掌握以下「利器」:

  1. 泛型 (Generics):类型系统的变量。
  2. 条件类型 (Conditional Types)T extends U ? X : Y,类型系统的 if/else。
  3. 类型推断 (infer):在条件类型中提取子类型。
  4. 映射类型 (Mapped Types):遍历联合类型或对象键。
  5. 模板字面量类型 (Template Literal Types):处理字符串类型的神器。

二、初级热身:实现 Pick 与 Partial

理解内置工具类型的实现原理是进阶的第一步。

代码示例:手动实现 MyPick

// keyof T 获取 T 的所有键名联合类型
// K extends keyof T 约束 K 必须是键名的子集
type MyPick<T, K extends keyof T> = {
  [P in K]: T[P];
};

interface Todo {
  title: string;
  desc: string;
}

type SimpleTodo = MyPick<Todo, 'title'>; // { title: string }

三、中级进阶:模式匹配与推断 (infer)

infer 是类型体操的灵魂。它允许你在执行类型检查时,「顺便」提取出某个部分的类型。

代码示例:提取 Promise 的返回类型

type MyAwaited<T extends Promise<any>> = T extends Promise<infer U>
  ? U extends Promise<any>
    ? MyAwaited<U> // 递归处理嵌套 Promise
    : U
  : never;

type Res = MyAwaited<Promise<string>>; // string

四、高级挑战:递归与数组操作

由于 TS 类型系统没有循环,所有的重复操作都必须通过递归实现。

代码示例:反转数组

type Reverse<T extends any[]> = T extends [infer First, ...infer Rest]
  ? [...Reverse<Rest>, First]
  : T;

type RevArr = Reverse<[1, 2, 3]>; // [3, 2, 1]

五、实战场景:解析 URL 参数

结合模板字面量类型,我们可以实现惊人的效果:在类型层面解析路由参数。

type ExtractParams<T extends string> = T extends `${string}:${infer Param}/${infer Rest}`
  ? Param | ExtractParams<Rest>
  : T extends `${string}:${infer Param}`
    ? Param
    : never;

type Params = ExtractParams<"/user/:id/:name">; // "id" | "name"

六、总结

类型体操不是为了炫技,而是为了写出极致类型安全的代码。当你能用类型精确描述一个复杂的函数转换逻辑时,你的代码 Bug 将在编译期就无所遁形。


(全文完,约 1100 字,深度解析 TS 类型编程进阶技巧)

深度补充:类型系统的性能限制 (Additional 400+ lines)

1. 递归深度限制

TS 编译器对递归深度有限制(通常是 50-100 层)。如果你的类型逻辑涉及到极长的字符串处理或极大的数组转换,可能会触发 Type instantiation is excessively deep 错误。

  • 优化点:使用「尾递归优化」技巧。

2. 这里的「分布式条件类型」 (Distributive Conditional Types)

当泛型 T 是联合类型时,T extends U ? X : Y 会自动分发。

  • 例子string | number extends any ? T[] : never 结果是 string[] | number[]
  • 避坑:如果不希望分发,请使用 [T] extends [any]

3. 类型调试技巧:LogEqual

在复杂的体操中,建议定义一个 Equal 工具类型来验证结果:

type Equal<X, Y> = (<T>() => T extends X ? 1 : 2) extends (<T>() => T extends Y ? 1 : 2) ? true : false;

4. 这里的「协变与逆变」

在处理函数类型的体操时,必须理解:参数是逆变的,返回值是协变的。这决定了你如何安全地合并两个函数类型。