本文由一缘原创整理,专注于 TypeScript 类型系统的进阶玩法与实战技巧,涵盖类型体操、类型推断、条件类型、实用技巧,适合所有 TS/前端开发者。

TypeScript 类型体操与实战技巧

TypeScript 类型系统极其强大,掌握类型体操能让你写出更安全、灵活的代码。


1. 条件类型与类型推断

type IsString<T> = T extends string ? true : false;
type A = IsString<'abc'>; // true
type B = IsString<123>;   // false

输出:

A = true
B = false

2. infer 关键字的妙用

type GetReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
type R1 = GetReturnType<() => number>; // number
type R2 = GetReturnType<(x: string) => boolean>; // boolean

输出:

R1 = number
R2 = boolean

3. 映射类型与递归类型

type DeepReadonly<T> = {
  readonly [K in keyof T]: T[K] extends object ? DeepReadonly<T[K]> : T[K];
};

type Obj = { a: { b: { c: number } }, d: string };
type ReadonlyObj = DeepReadonly<Obj>;

输出:

ReadonlyObj = {
  readonly a: { readonly b: { readonly c: number } };
  readonly d: string;
}

4. 联合类型与分布式条件类型

type ToArray<T> = T extends any ? T[] : never;
type A = ToArray<string | number>;

输出:

A = string[] | number[]

5. 类型体操实战:实现 Pick、Exclude、Parameters

5.1. 手写 Pick

type MyPick<T, K extends keyof T> = {
  [P in K]: T[P];
};
type Obj = { a: number; b: string; c: boolean };
type Picked = MyPick<Obj, 'a' | 'c'>;

输出:

Picked = { a: number; c: boolean }

5.2. 手写 Exclude

type MyExclude<T, U> = T extends U ? never : T;
type E = MyExclude<'a' | 'b' | 'c', 'a' | 'c'>;

输出:

E = 'b'

5.3. 手写 Parameters

type MyParameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;
type P = MyParameters<(x: number, y: string) => void>;

输出:

P = [number, string]

6. 字符串字面量类型与模板字符串类型

type EventName<T extends string> = `on${Capitalize<T>}`;
type Click = EventName<'click'>; // 'onClick'
type Hover = EventName<'hover'>; // 'onHover'

输出:

Click = 'onClick'
Hover = 'onHover'

7. 实战技巧:类型安全的 API 响应处理

interface ApiResponse<T> {
  code: number;
  data: T;
  msg: string;
}

type User = { id: number; name: string };
type UserRes = ApiResponse<User>;

输出:

UserRes = { code: number; data: { id: number; name: string }; msg: string }

8. 类型体操进阶:深度可选 DeepPartial

type DeepPartial<T> = {
  [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
};

type Obj = { a: { b: { c: number } }, d: string };
type PartialObj = DeepPartial<Obj>;

输出:

PartialObj = {
  a?: { b?: { c?: number } };
  d?: string;
}

9. 类型体操题目推荐

  • 实现 PromiseAll 类型推断
  • 实现 Chainable Options
  • 实现 TupleToObject
  • 实现 LastOfArray

(可在 type-challenges 找到更多练习)


10. 总结与最佳实践

  • 善用类型推断、条件类型、映射类型提升类型安全
  • 类型体操能极大提升 TS 代码的健壮性和灵活性
  • 推荐多做 type-challenges 练习,提升类型系统掌控力