引言
TypeScript 5.x 带来了许多激动人心的新特性,尤其是装饰器的标准化、条件类型的增强以及类型系统性能的显著提升。然而,许多开发者仍停留在基础用法上,未能充分利用这些特性来提升代码质量。本文将带你深入实践,掌握 TypeScript 5.x 的进阶用法,包括装饰器、条件类型以及性能优化技巧。
一、装饰器:从实验到标准
TypeScript 5.x 正式实现了 Stage 3 装饰器提案,与之前的实验性装饰器有显著差异。新装饰器更简洁、类型安全,并且与 JavaScript 标准对齐。
1.1 启用新装饰器
在 tsconfig.json 中设置:
{
"compilerOptions": {
"target": "ES2022",
"experimentalDecorators": false // 关闭旧装饰器
}
}
1.2 基本用法
新装饰器函数接收两个参数:target(被装饰的元素)和 context(包含元数据的对象)。
function logged<T extends (...args: any[]) => any>(
target: T,
context: ClassMethodDecoratorContext
) {
return function (this: any, ...args: Parameters<T>) {
console.log(`Calling ${String(context.name)} with`, args);
return target.call(this, ...args);
};
}
class Calculator {
@logged
add(a: number, b: number): number {
return a + b;
}
}
const calc = new Calculator();
calc.add(2, 3); // 输出日志
💡 注意:新装饰器不能用于参数装饰器;如果需要参数装饰器,仍需使用旧装饰器(experimentalDecorators: true),但两者不可混用。
1.3 自定义装饰器工厂
装饰器工厂返回一个装饰器函数,可以接受参数:
function validate(min: number, max: number) {
return function (
target: any,
context: ClassAccessorDecoratorContext
) {
return {
get(this: any) {
return target.get.call(this);
},
set(this: any, value: number) {
if (value < min || value > max) {
throw new Error(`Value must be between ${min} and ${max}`);
}
target.set.call(this, value);
}
};
};
}
class Temperature {
@validate(0, 100)
accessor celsius: number = 0;
}
const temp = new Temperature();
temp.celsius = 50; // 正常
temp.celsius = 150; // 抛出错误
二、条件类型:从基础到高级模式
条件类型让类型计算变得灵活,TypeScript 5.x 进一步增强了其能力。
2.1 分布式条件类型
当条件类型用于泛型且泛型为联合类型时,会自动分布式求值:
type ToArray<T> = T extends unknown ? T[] : never;
type Result = ToArray<string | number>; // string[] | number[]
2.2 模板字面量类型与条件类型结合
type EventName<T extends string> = `${T}Changed`;
type Handler<T extends string> = (event: EventName<T>) => void;
function createListener<T extends string>(event: T, handler: Handler<T>) {}
createListener('name', (event) => {
// event 类型为 "nameChanged"
});
2.3 infer 关键字的高级用法
infer 用于在条件类型中推断类型变量:
type ReturnTypeOf<T> = T extends (...args: any[]) => infer R ? R : never;
function greet() { return 'hello'; }
type GreetReturn = ReturnTypeOf<typeof greet>; // string
更复杂的例子:提取 Promise 的返回值类型:
type Unwrap<T> = T extends Promise<infer U> ? Unwrap<U> : T;
type Result = Unwrap<Promise<Promise<string>>>; // string
💡 注意:infer 只能在条件类型的 extends 子句中使用。
三、性能优化:让类型检查飞起来
TypeScript 5.x 通过多种方式提升了类型检查性能。
3.1 使用 --isolatedModules 和 --verbatimModuleSyntax
这两个选项可以显著减少编译时的类型检查工作:
{
"compilerOptions": {
"isolatedModules": true,
"verbatimModuleSyntax": true
}
}
isolatedModules:确保每个文件可以独立编译,避免跨文件类型推断。verbatimModuleSyntax:保留模块语法,避免不必要的类型擦除。
3.2 避免大型联合类型
大型联合类型(超过 50 个成员)会严重影响性能。使用接口或类型映射替代:
// 不推荐
type Status = 'a' | 'b' | ... | 'z'; // 26个
// 推荐
interface StatusMap {
a: any;
b: any;
// ...
}
type Status = keyof StatusMap;
3.3 使用 @ts-expect-error 替代 @ts-ignore
@ts-ignore 会跳过类型检查,但可能隐藏错误。@ts-expect-error 更安全:
// @ts-expect-error - 下一行预期有错误
const x: number = 'string'; // 错误被预期,不会报错
3.4 利用 satisfies 操作符
satisfies 在 4.9 引入,5.x 增强,用于验证类型但不改变推断结果:
const palette = {
red: [255, 0, 0],
green: '#00ff00',
} satisfies Record<string, string | number[]>;
// palette.red 推断为 number[],而非 string | number[]
palette.red.map(x => x); // 正确
四、实战:构建类型安全的 API 客户端
结合上述特性,我们构建一个类型安全的 HTTP 客户端。
// 定义 API 端点类型
type Endpoint = {
'/users': { method: 'GET'; response: User[] };
'/users/:id': { method: 'GET'; response: User };
'/users': { method: 'POST'; body: Omit<User, 'id'>; response: User };
};
// 条件类型提取响应类型
type ResponseOf<T extends keyof Endpoint> = Endpoint[T] extends { response: infer R } ? R : never;
// 请求函数
async function request<T extends keyof Endpoint>(
url: T,
options?: { method?: Endpoint[T]['method']; body?: any }
): Promise<ResponseOf<T>> {
const response = await fetch(url, options);
return response.json();
}
// 使用
const users = await request('/users'); // 类型为 User[]
const user = await request('/users/:id', { method: 'GET' }); // 类型为 User
五、总结
TypeScript 5.x 的装饰器、条件类型和性能优化为开发者提供了更强大的工具。通过本文的实践,你应该能够:
- 使用新装饰器编写元编程代码
- 利用条件类型进行复杂的类型计算
- 优化项目配置以提升类型检查速度
下一步,可以探索 TypeScript 5.x 的模块解析策略(moduleResolution: 'bundler')以及迭代器辅助方法(Iterator 类型)等特性。