高级类型技巧(Advanced Type Techniques)
概述
TypeScript 提供了丰富的高级类型特性,用于创建灵活、类型安全的代码。
模板字面量类型
基本语法
// 模板字面量类型
type EventName = `on${Capitalize<'click' | 'focus' | 'blur'>}`;
// 'onClick' | 'onFocus' | 'onBlur'
// 联合类型分发
type Color = 'red' | 'blue';
type Size = 'small' | 'large';
type Style = `${Size}-${Color}`;
// 'small-red' | 'small-blue' | 'large-red' | 'large-blue'
实际应用
// CSS 类名生成
type Spacing = 'p' | 'm';
type Direction = 't' | 'r' | 'b' | 'l' | 'x' | 'y';
type Size = '1' | '2' | '3' | '4' | '5';
type SpacingClass = `${Spacing}${Direction}-${Size}`;
// 'p-1' | 'p-2' | 'm-1' | 'm-2' | ...
// 事件处理器
type EventHandler<T extends string> = `on${Capitalize<T>}`;
type ButtonEvents = EventHandler<'click' | 'hover' | 'focus'>;
// 'onClick' | 'onHover' | 'onFocus'
类型推断
infer 关键字
// 提取函数返回类型
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
function createUser() {
return { id: 1, name: 'John' };
}
type User = ReturnType<typeof createUser>;
// { id: number; name: string; }
// 提取 Promise 类型
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
type A = UnwrapPromise<Promise<string>>; // string
// 提取数组元素类型
type ElementOf<T> = T extends (infer E)[] ? E : never;
type B = ElementOf<string[]>; // string
条件类型推断
// 复杂类型推断
type FunctionParams<T> = T extends (...args: infer P) => any ? P : never;
type FunctionReturn<T> = T extends (...args: any[]) => infer R ? R : never;
function add(a: number, b: number): number {
return a + b;
}
type AddParams = FunctionParams<typeof add>; // [number, number]
type AddReturn = FunctionReturn<typeof add>; // number
类型收窄
可辨识联合类型
// 可辨识联合类型
interface Square {
kind: 'square';
size: number;
}
interface Circle {
kind: 'circle';
radius: number;
}
interface Rectangle {
kind: 'rectangle';
width: number;
height: number;
}
type Shape = Square | Circle | Rectangle;
function area(shape: Shape): number {
switch (shape.kind) {
case 'square':
return shape.size ** 2;
case 'circle':
return Math.PI * shape.radius ** 2;
case 'rectangle':
return shape.width * shape.height;
}
}
守卫类型
// 自定义类型守卫
interface Cat {
meow: () => void;
}
interface Dog {
bark: () => void;
}
function isCat(animal: Cat | Dog): animal is Cat {
return 'meow' in animal;
}
function makeSound(animal: Cat | Dog): void {
if (isCat(animal)) {
animal.meow();
} else {
animal.bark();
}
}
类型编程
递归类型
// 递归类型
type DeepReadonly<T> = T extends (infer U)[]
? ReadonlyArray<DeepReadonly<U>>
: T extends object
? { readonly [P in keyof T]: DeepReadonly<T[P]> }
: T;
interface User {
id: number;
name: string;
address: {
city: string;
country: string;
};
}
type ReadonlyUser = DeepReadonly<User>;
类型级计算
// 类型级计算
type Length<T extends any[]> = T['length'];
type Zero = Length<[]>; // 0
type One = Length<[1]>; // 1
type Two = Length<[1, 2]>; // 2
// 元组操作
type Push<T extends any[], V> = [...T, V];
type Pop<T extends any[]> = T extends [...infer Rest, any] ? Rest : never;
type A = Push<[1, 2], 3>; // [1, 2, 3]
type B = Pop<[1, 2, 3]>; // [1, 2]
实际应用示例
1. 路由类型
// 路由类型
type Route = '/' | '/about' | '/users' | '/users/:id';
type RouteParams<T extends string> = T extends `${string}:${infer Param}/${infer Rest}`
? Param | RouteParams<Rest>
: T extends `${string}:${infer Param}`
? Param
: never;
type UserRouteParams = RouteParams<'/users/:id'>; // 'id'
type ComplexParams = RouteParams<'/users/:id/posts/:postId'>; // 'id' | 'postId'
2. 状态机类型
// 状态机类型
type State = 'idle' | 'loading' | 'success' | 'error';
type Event = 'FETCH' | 'RESOLVE' | 'REJECT' | 'RESET';
type Transition<S extends State, E extends Event> =
S extends 'idle'
? E extends 'FETCH' ? 'loading' : never
: S extends 'loading'
? E extends 'RESOLVE' ? 'success' : E extends 'REJECT' ? 'error' : never
: S extends 'success' | 'error'
? E extends 'RESET' ? 'idle' : never
: never;
type T1 = Transition<'idle', 'FETCH'>; // 'loading'
type T2 = Transition<'loading', 'RESOLVE'>; // 'success'
type T3 = Transition<'loading', 'REJECT'>; // 'error'
3. 表单类型
// 表单类型
interface FormField<T> {
value: T;
error?: string;
touched: boolean;
}
type Form<T> = {
[K in keyof T]: FormField<T[K]>;
};
interface LoginForm {
username: string;
password: string;
remember: boolean;
}
type LoginFormFields = Form<LoginForm>;
4. API 类型
// API 类型
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
type Endpoint = {
[K in HttpMethod]?: {
path: string;
response: any;
};
};
type Api = {
'/users': {
GET: {
path: '/users';
response: User[];
};
POST: {
path: '/users';
response: User;
};
};
'/users/:id': {
GET: {
path: '/users/:id';
response: User;
};
PUT: {
path: '/users/:id';
response: User;
};
DELETE: {
path: '/users/:id';
response: void;
};
};
};
最佳实践
- 使用模板字面量类型:生成字符串类型
- 使用 infer 提取类型:从复杂类型中提取部分
- 使用递归类型:处理嵌套结构
- 避免过度复杂:保持类型可读
// 好的做法
type EventName<T extends string> = `on${Capitalize<T>}`;
// 避免
type ComplexType<T> = T extends A
? T extends B
? T extends C
? D
: E
: F
: G;
参考
目录