TypeScript 5.x 实战技巧:类型系统进阶指南
TypeScript 5.x 带来了众多新特性,本文深入讲解类型系统的高级用法,让你的代码更加类型安全。
const 类型参数
TypeScript 5.0 引入了 const 类型参数,这是一个强大的新特性:
function makeRoute<const T extends string>(route: T) {
return route;
}
const route = makeRoute("/api/users"); // 类型为 "/api/users",而非 string装饰器 Decorators
TypeScript 5.0 正式支持 ECMAScript 装饰器标准:
function logged(target: any, key: string, descriptor: PropertyDescriptor) {
const original = descriptor.value;
descriptor.value = function(...args: any[]) {
console.log(`Calling ${key} with`, args);
return original.apply(this, args);
};
return descriptor;
}
class Calculator {
@logged
add(a: number, b: number) {
return a + b;
}
}高级类型技巧
1. 条件类型嵌套
type DeepPartial<T> = T extends object
? { [P in keyof T]?: DeepPartial<T[P]> }
: T;
// 用于部分更新嵌套对象
function updateUser(user: DeepPartial<User>) { ... }2. 模板字面量类型
type EventName = `on${Capitalize<string>}`;
type ButtonEvents = {
onClick: () => void;
onMouseEnter: () => void;
};3. 映射类型修饰符
// 深度只读类型
type DeepReadonly<T> = {
readonly [P in keyof T]: T[P] extends object
? DeepReadonly<T[P]>
: T[P];
};infer 关键字妙用
infer 允许在条件类型中提取类型:
// 提取函数返回值类型
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
// 提取数组元素类型
type ElementType<T> = T extends (infer E)[] ? E : never;
// 提取 Promise resolved 类型
type Awaited<T> = T extends Promise<infer U> ? Awaited<U> : T;类型守卫与断言
// 自定义类型守卫
function isString(value: unknown): value is string {
return typeof value === "string";
}
// 断言函数
function assertIsDefined<T>(value: T, msg?: string): asserts value is NonNullable<T> {
if (value === null || value === undefined) {
throw new Error(msg ?? "Value should be defined");
}
}实战建议
- 优先使用 interface,除非需要extends多个类型
- 善用 readonly 防止意外修改
- 类型太复杂时,用 type 别名简化
- 优先使用 unknown 而非 any
- 善用 satisfies 验证类型而非宽化
总结
TypeScript 的类型系统非常强大,熟练掌握这些高级技巧能让你的代码更加健壮和易维护。