TypeScript 的类型系统是图灵完备的,这意味着你可以在类型层面实现复杂的逻辑。 掌握高级类型不仅能提升代码安全性,还能极大地改善开发体验。
泛型基础回顾
function first<T>(arr: T[]): T | undefined {
return arr[0];
}
const a = first([1, 2, 3]); // number | undefined
const b = first(["a", "b"]); // string | undefined
function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
return obj[key];
}
条件类型
// 基础语法: T extends U ? X : Y
type IsString<T> = T extends string ? true : false;
type A = IsString<"hello">; // true
type B = IsString<number>; // false
// 提取 Promise 内部类型
type Unwrap<T> = T extends Promise<infer U> ? U : T;
infer 关键字
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
type Fn = (x: number) => string;
type R = ReturnType<Fn>; // string
type ElementType<T> = T extends (infer E)[] ? E : T;
模板字面量类型
type EventName<T extends string> = `on${Capitalize<T>}`;
type ClickEvent = EventName<"click">; // "onClick"
// 类型安全的事件系统
type EventMap = { click: { x: number; y: number }; focus: void; change: string };
type EventHandler<E extends keyof EventMap> = (event: EventMap[E]) => void;
type ListenerMap = {
[K in keyof EventMap as `on${Capitalize<K>}`]: EventHandler<K>
};
映射类型实战
type DeepReadonly<T> = {
readonly [K in keyof T]: T[K] extends object ? DeepReadonly<T[K]> : T[K];
};
type DeepPartial<T> = {
[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K] | null;
};
实战:类型安全的 API 请求库
interface ApiRoutes {
"/users": {
GET: { response: { id: number; name: string }[] };
POST: { body: { name: string }; response: { id: number } };
};
"/users/[id]": {
GET: { params: { id: string }; response: { id: number; name: string } };
};
}
async function request<
Path extends keyof ApiRoutes,
Method extends keyof ApiRoutes[Path]
>(path: Path, method: Method, ...args: [...]): Promise<...> {
return {} as any;
}
const users = await request("/users", "GET");
// users 类型自动推断为 { id: number; name: string }[]
提示:高级类型虽好,但要适度使用。过于复杂的类型体操会降低代码可读性。
好的类型设计是在安全性和简洁性之间找到平衡。
总结
TypeScript 的高级类型系统为构建类型安全的应用程序提供了强大的工具。
泛型提供复用性,条件类型和 infer 提供灵活性,
模板字面量类型和映射类型让字符串和对象类型变换变得简单。