TypeScript 5.x 实战:新特性与迁移避坑
目录
先说要不要升
TypeScript 升级政策是:每个 major 版本支持 24 个月。
目前(2025年):
- TS 5.0+ 是主流
- TS 4.x 进入维护模式
- TS 5.6 是最新稳定版
建议:新项目直接用最新版,老项目逐 minor 版本升级,不要跳版本。
5.0: 装饰器 (Decorators)
最重要的变化:装饰器终于标准化了。
// TS 5.0 装饰器语法
function logged(target: any, context: ClassMethodDecoratorContext) {
const methodName = String(context.name);
return function (this: any, ...args: any[]) {
console.log(`Calling ${methodName}`);
return target.apply(this, args);
};
}
class Calculator {
@logged
add(a: number, b: number) {
return a + b;
}
}这是 ECMAScript 正式的装饰器提案,跟之前用 experimentalDecorators 不一样。
对 React 项目的影响
// 以前:需要 babel 配置
// 现在:TypeScript 原生支持
function withAuth(target: any, context: ClassMethodDecoratorContext) {
return function (this: any, ...args: any[]) {
if (!currentUser) {
throw new Error('Unauthorized');
}
return target.apply(this, args);
};
}
class Dashboard {
@withAuth
async fetchData() {
// 只有登录用户能访问
}
}5.1: 独立的类型推导改进
// 5.1 之前:return type 必须显式写
function createElement(tag: string): HTMLElement {
return document.createElement(tag);
}
// 5.1 支持:显式返回 undefined
function maybeCreateElement(tag: string): HTMLElement | undefined {
if (!tag) return undefined;
return document.createElement(tag);
}
// 5.1 支持:泛型函数可以返回不同类型
function find<T>(arr: T[], predicate: (item: T) => boolean): T | undefined {
return arr.find(predicate);
}这个改进让很多以前要写复杂类型 hack 的场景变得简单。
5.2: using 和 Explicit Resource Management
类似 Python 的 with 语句:
// 5.2 新增:using 声明
function readFile(path: string) {
const file = using f = openFile(path); // 自动管理资源
return f.read();
} // file 自动关闭
// 配合 Symbol.dispose
class DatabaseConnection {
[Symbol.dispose]() {
this.close();
}
}
function query() {
using conn = new DatabaseConnection();
conn.execute("SELECT * FROM users");
} // 自动关闭连接
对需要手动管理连接/文件/锁的场景很有用,减少 memory leak。
5.4: NoInfer utility type
// 5.4 新增 NoInfer
function createSignal<T>(value: T, defaultValue: NoInfer<T>) {
return { value: value ?? defaultValue };
}
// 以前这样写会 type error
createSignal("hello", "world"); // T 被推断为 "hello",但 defaultValue 也是 string,没问题
// NoInfer 防止类型被进一步推断
// 用于 API 设计中强制某些参数用字面量类型
5.5: 推断的 Predicates 类型改进
// 5.5 之前:array.filter 后要 cast
const users = [{ name: "Alice" }, { name: "Bob" }, null];
const names = users
.filter((u): u is NonNullable<typeof u> => u !== null)
.map(u => u.name);
// 5.5:TypeScript 自动推断 predicate
const names2 = users
.filter(u => u !== null) // TS 自动推断返回类型
.map(u => u.name); // u 现在是 { name: string },不用手动写类型断言
这个改进让代码简洁很多。
迁移注意事项
逐版本迁移
# 不要跳版本
tsc --version
# 5.5.4 → 迁移到 5.6
# 逐 minor 升级
npm install [email protected]
# 跑测试
npm test
# 确认没问题再继续常见 breaking changes
noImplicitAny更严格:有些隐式 any 现在报错useDefineForClassFields:和 ES2022 语义对齐,可能影响 class field 行为isolatedModules:每个文件必须是独立可编译的
检查 tsconfig
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"isolatedModules": true
}
}总结
TypeScript 5.x 最有价值的新特性:
| 版本 | 特性 | 实用度 |
|---|---|---|
| 5.0 | 标准装饰器 | ⭐⭐⭐⭐ 前端必用 |
| 5.1 | 类型推导改进 | ⭐⭐⭐ 减少类型 hack |
| 5.2 | using 资源管理 | ⭐⭐⭐ 文件/连接管理 |
| 5.4 | NoInfer | ⭐⭐ API 设计用 |
| 5.5 | Predicate 自动推断 | ⭐⭐⭐⭐ 简化 filter/map |
建议:保持 minor 版本更新,每次更新只升一个版本,跑测试确认。