深色模式
TypeScript 5.4 正式发布,带来了一些实用的类型系统改进和对 TC39 新提案的支持。从架构视角看,有几个特性对团队代码质量提升明显。
Object.groupBy 和 Map.groupBy
之前分组操作需要写 reduce:
typescript
// 以前:手写 reduce
const grouped = users.reduce((acc, user) => {
const key = user.role;
if (!acc[key]) acc[key] = [];
acc[key].push(user);
return acc;
}, {} as Record<string, User[]>);
// TypeScript 5.4 + ES2024
const grouped = Object.groupBy(users, (user) => user.role);
// grouped 的类型是 Partial<Record<string, User[]>>返回 Partial 是合理的,因为分组结果可能不包含所有可能的 key。
Map.groupBy 则返回 Map<K, V[]>,支持任意类型作为 key:
typescript
const byDept = Map.groupBy(users, (u) => departments.get(u.deptId)!);
// 返回 Map<Department, User[]>NoIntrinsic 类型安全增强
TypeScript 5.4 引入了 NoIntrinsic 类型,这是对模板字面量类型的增强。在处理 HTML 属性映射时更精确:
typescript
// 类型推断更精准,条件类型中交叉类型分发更正确
type ExtractId<T> = T extends `${infer Prefix}_${infer Suffix}`
? `${Prefix}_id`
: never;
type Result = ExtractId<"user_name" | "post_title">;
// "user_id" | "post_id"改进的闭包类型缩小
一个很实用的改进:闭包中捕获的变量现在能正确保持类型缩小:
typescript
function processValue(input: string | number) {
if (typeof input === "string") {
// TS 5.4 之前:闭包中 input 可能丢失 string 类型
const handler = () => {
return input.toUpperCase(); // 现在能正确识别为 string
};
}
}in 运算符的类型收窄增强
typescript
interface Dog {
bark(): void;
}
interface Cat {
meow(): void;
}
function handlePet(pet: Dog | Cat) {
if ("bark" in pet) {
pet.bark(); // TS 5.4 之前这里可能不够精确
}
}在项目中的落地
我们团队在升级 TS 5.4 时,重点关注了几个场景:
- 数据处理层:把自定义 groupBy 工具函数替换为原生
Object.groupBy,减少约 200 行重复代码 - 类型安全:利用改进的条件类型推断,简化了 API 响应类型的自动推导
- 团队规范:更新 ESLint 规则,检测并标记可以使用原生 API 的地方
小结
Object.groupBy/Map.groupBy:原生分组 API,减少重复工具函数- 闭包类型缩小:闭包中捕获的变量保持类型信息
in运算符增强:更精确的类型收窄- 条件类型推断改进:交叉类型处理更准确
- 建议团队统一升级,配合
target: "ES2024"使用