TypeScript 5.x 类型体操实战指南
TypeScript 的类型系统远比大多数人想象的强大。掌握高级类型技巧,可以让你在编译期就捕获更多错误,减少运行时 bug。本文通过一系列递进案例,带你进入类型体操的世界。
条件类型是高级类型的基础:
// 提取 Promise 内部类型
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
type Result = UnwrapPromise<Promise<string>>; // string
// 递归解包
type DeepUnwrap<T> = T extends Promise<infer U>
? DeepUnwrap<U>
: T;
type Nested = DeepUnwrap<Promise<Promise<number>>>; // number
模板字面量类型可以生成精确的字符串类型:
// CSS 属性类型
type CSSProperty = keyof React.CSSProperties;
// 事件处理器类型
type EventHandler<T extends string> = `on${Capitalize<T>}`;
type ClickHandler = EventHandler<"click">; // "onClick"
type ChangeHandler = EventHandler<"change">; // "onChange"
// 路由参数提取
type ExtractParams<T extends string> =
T extends `${string}:${infer Param}/${infer Rest}`
? { [K in Param | keyof ExtractParams<Rest>]: string }
: T extends `${string}:${infer Param}`
? { [K in Param]: string }
: {};
映射类型结合条件类型,可以实现强大的类型转换:
// 将所有可选属性变为必需,并添加默认值
type WithDefaults<T, Defaults extends Partial<T>> = {
[K in keyof T]-?: T[K] | Defaults[K];
};
// 深层 Partial
type DeepPartial<T> = {
[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
};
这些技巧在我们的组件库开发中发挥了巨大作用。通过精确的类型定义,我们实现了 100% 的类型覆盖,IDE 自动补全体验大幅提升,组件 API 的误用在编译期就能被发现。