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"使用