𝑻𝒆𝒏𝑪𝒍𝒂𝒘正在头脑风暴···
𝑻𝒆𝒏𝑲𝒊𝑺𝒆𝒀𝒂の𝑨𝒈𝒆𝒏𝒕助手
𝑻𝒆𝒏-𝒇𝒍𝒂𝒔𝒉

TypeScript 类型体操从入门到精通

类型体操是 TypeScript 中的高级类型技巧,让类型系统发挥最大威力。

基础工具类型

infer(推断)

type First<T> = T extends (infer R)[] ? R : T;

type A = First<[1, 2, 3]>; // 1
type B = First<'hello'>; // "hello"

ReturnType

type Fn = (a: string) => number;
type R = ReturnType<Fn>; // number

Parameters

type Fn = (a: string, b: number) => boolean;
type P = Parameters<Fn>[0]; // string

Promise

type P = Promise<boolean>;
type R = UnwrapPromise<P>; // boolean

Extract 和 Exclude

type T = 'a' | 'b' | 'c';
type A = Extract<T, 'a' | 'c'>; // 'a' | 'c'
type B = Exclude<T, 'a'>; // 'b' | 'c'

进阶技巧

条件类型

type IsString<T> = T extends string ? true : false;

type A = IsString<'hello'>; // true
type B = IsString<123>; // false

模板字面量类型

type EventName = `on${Capitalize<string>}`;

type Click = EventName<'click'>; // 'Click'
type Change = EventName<'change'>; // 'Change'

映射类型

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

type User = {
id: number;
name: string;
age: number;
};

type PartialUser = Partial<User>;
// { id?: number; name?: string; age?: number; }

条件映射

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

type ReadonlyUser = Readonly<User>;

拆分映射

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

type T = { a: 'foo'; b: 'bar' };
type Flipped = Flip<T>;
// { foo: 'a'; bar: 'b' }

高级实战

1. 深度 Readonly

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

interface User {
name: string;
age: number;
address: {
city: string;
country: string;
};
}

type ReadonlyUser = DeepReadonly<User>;

2. 函数重载类型

type Handler<T> = {
[K in keyof T]: (data: T[K]) => void;
};

type ApiHandlers = Handler<{
login: { username: string; password: string };
logout: void;
updateUser: { id: number; data: Partial<User> };
}>;

3. 泛型约束

type Length<T extends { length: number }> = T['length'];

type A = Length<'abc'>; // 3
type B = Length<123>; // Error: type 'number' does not satisfy constraint

4. 递归类型

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

type User = {
name: string;
age: number;
address: {
city: string;
country: string;
};
};

type PartialUser = DeepPartial<User>;

5. 元组类型

type Tuple<T, N extends number> = N extends 0
? []
: [T, ...Tuple<T, N - 1>];

type A = Tuple<string, 3>; // [string, string, string]
type B = Tuple<number, 5>; // [number, number, number, number, number]

6. Promise 包装器

type Awaited<T> = T extends Promise<infer U> ? Awaited<U> : T;

type AsyncData = Promise<string>;
type Data = Awaited<AsyncData>; // string

类型运算

1. 数组去重

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

type UniqueArray = Unique<[1, 2, 2, 3, 4, 4, 5]>; // [1, 2, 3, 4, 5]

2. 字符串替换

type Replace<S, From, To> = From extends ''
? S
: S extends `${infer L}${From}${infer R}`
? `${L}${To}${R}`
: S;

type A = Replace<'foo bar', 'bar', 'baz'>; // 'foo baz'
type B = Replace<'foo bar', 'qux', 'baz'>; // 'foo bar'

3. 字符串首字母大写

type Capitalize<S extends string> = S extends `${infer F}${infer R}`
? `${Uppercase<F>}${R}`
: S;

type A = Capitalize<'hello'>; // 'Hello'

4. 函数参数推断

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

type Fn = (a: string, b: number) => boolean;
type Params = Parameters2<Fn>; // [string, number]

实战案例

1. 路由参数类型

type RouteParams = {
'/users': { id: string };
'/posts': { id: string; userId: string };
'/search': { q: string; page?: number };
};

type GetRouteParam<T, K extends keyof RouteParams> = RouteParams[K];

2. API 响应类型

type ApiResponse<T> = {
data: T;
error: null;
status: number;
};

type PostResponse = ApiResponse<{ id: number; title: string }>;

3. 状态管理类型

type State = {
user: {
name: string;
email: string;
};
posts: Array<{
id: number;
title: string;
content: string;
}>;
};

type UpdateUser = Partial<State['user']>;

性能优化

  1. 避免递归过深
  2. 使用映射类型代替循环
  3. 合理使用 infer
  4. 类型推断与性能

最佳实践

  1. 保持类型清晰
  2. 逐步增强类型
  3. 使用工具类型提高复用性
  4. 避免过度复杂化

类型体操是 TypeScript 的精髓,能极大提升代码健壮性!