TypeScript 5.0 现已发布:全新的装饰器,速度、内存和包大小优化
微软在上周发布了 TypeScript 5.0 beta 版本,希望在助其瘦身之余简化使用方式、加快运行速度。此次公布的 beta 版还引入新的装饰器标准,使用户能够以可重用的方式自定义类及其成员。
相对于 TypeScript 4.9 在速度和大小方面的提升:
此次 beta 版的一大亮点,在于合并了新的装饰器标准,使用户能够以可重用的方式自定义类及其成员。TypeScript 项目经理 Daniel Rosenwasser 最近在官方博客上写道,这些实验性的装饰器非常重要,在支持旧版本装饰器的同时将可选编译器标志—experimentalDecorators 设为始终启用。Rosenwasser 表示,很多一直在用 --experimentalDecorators 的开发者已经意识到,之前在 TypeScript 中使用装饰器却不启用此标志,均会产生错误消息。
Rosenwasser 还谈到 TypeScript 中关于 enums 的老问题,5.0 beta 版如何解决其中部分问题,同时减少了声明各类 enums 时所需理解的概念数量。
TypeScript 属于开源编程语言加 JavaScript 的一个超集,以 JavaScript 为基础并实现了功能扩展,目前由微软负责开发和维护。
TypeScript 5.0 中的新装饰器提案允许开发者编写出更清晰、更易于维护的代码,并能够以可重用的方式自定义类及其成员。虽然新的装饰器与 --emitDecoratorMetadata 不兼容且不支持参数装饰,但微软预计后续推出的 ECMAScript 提案有望解决这些限制。
除了新的装饰器提案之外,TypeScript 5.0 还引入多项改进,例如对构造函数中的参数装饰器进行更精确的类型检查、const 注释,以及允许 extends 字段获取多个条目的能力等。
TypeScript 5.0 版本还提供新的模块解析选项、性能增强和更详尽的 switch/case 补全功能。
TypeScript 以 ECMAScript 2018 为目标,因此 Node.js 用户至少需要使用 Node.js 10 或更高的版本。
要使用此 beta 版本,可以通过 NuGet 或者以下 npm 命令获取:
npm install typescript@beta
这里我们具体探究一些新功能,并通过代码示例帮助大家开启 TypeScript 5.0 之旅。
TypeScript 5.0 引入一项新功能,其中所有 enum 均为 union enum。这意味着每个 enum 成员现在都有自己的唯一类型,即使是由函数调用初始化的也不例外。以往,如果是通过函数调用初始化的 enum 成员,则 TypeScript 会使用旧的 enum 策略并导致 union 和字面量类型的优势失效。在新功能的支持下,开发者现可缩小所有 enum 范围,并将其成员作为类型来引用。
enum E {
A = 'a',
B = 'b',
C = Math.random() > 0.5 ? 'c' : 'd'
}
type EKeys = keyof typeof E; // 'A' | 'B' | 'C'
type EValues = typeof E[keyof typeof E]; // 'a' | 'b' | 'c' | 'd'
function f(e: E) {
switch (e) {
case E.A:
// This block is only executed if `e` is `'a'`
break;
case E.B:
// This block is only executed if `e` is `'b'`
break;
case E.C:
// This block is only executed if `e` is either `'c'` or `'d'`
break;
}
}
在以上示例中,enum E 具有 3 个成员,其中 E.C 使用函数调用通过三元运算符进行初始化。借助 TypeScript 5.0 中的新功能,所有 enum 成员都拥有自己的独特类型。在这里,E.C 具有'c' | 'd'类型,而不再像旧版本中那样具有 string 类型。f 函数则使用 switch 语句将 e 的类型缩小为 enum 成员之一,从而实现更好的类型检查和推断。
TypeScript 5.0 引入了将 const 修饰符添加至类型参数声明的功能,也就是默认做 const-like 推断。这项功能非常适合那些需要具体类型,而 TypeScript 已经推断出较通用类型的场景。以往,为了实现 const-like 推断,开发者需要在某些位置添加“as const”。Const 修饰符会影响调用中编写的对象、数组和原始表达式的推断,但不会拒绝可变值、或者说需要不可变约束。因此,开发者必须牢记 const 修饰符的行为以确保正确使用。
type HasNames = { readonly names: string[] };
function getNamesExactly<const T extends HasNames>(arg: T): T['names'] {
return arg.names;
}
// Inferred type: readonly ["Alice", "Bob", "Eve"]
const names = getNamesExactly({ names: ["Alice", "Bob", "Eve"] } as const);
在此示例中,我们定义了一个泛型函数 getNamesExactly,它会接受用于扩展 HasNames 接口的类型 T 的一条参数,其中包含作为 names 属性的字符串数组。
在 TypeScript 5.0 之前,arg.names 的推断类型为 string[],但如果我们需要的是 readonly string[],则需要在调用函数时使用 as const 进行断言。
而在 TypeScript 5.0 中,我们可以将 const 修饰符添加至类型参数声明当中,借此默认进行 const-like 推断。这样就能在调用中省略 as const 断言,且仍然推断出更具体的 readonly string[] 类型。
在编写 switch 语句时,TypeScript 现在可以检测被检查的值是否具有字面类型。如果是,则通过补全对每个未发现的 case 做 scaffold out。
可以在 GitHub 上(https://github.com/microsoft/TypeScript/pull/50996)参阅具体实现。
TypeScript 5.0 提供新的“导出类型”功能,能够在重新导出的语句中添加对仅类型导入的支持,例如 export from "module" 和 export * as ns from "module"。
示例为从 vehicles.ts 模块导出的 Spaceship 类,之后使用 export type * as vehicles from "./vehicles"在 models/index.ts 模块中进行重新导出。在 main.ts 当中,重新导出的 vehicles 命名空间被导入,并用于对 takeASpaceship 函数中的参数进行类型检查。但请注意,在 makeASpaceship 函数中创建新的 Spaceship 对象会导致错误,因为 vehicles 命名空间是作为仅类型导入进行导出的,不可用作值。
// models/vehicles.ts
export class Spaceship {
// ...
}
// models/index.ts
export type * as vehicles from "./vehicles";
// main.ts
import { vehicles } from "./models";
function takeASpaceship(s: vehicles.Spaceship) {
// ok - `vehicles` only used in a type position
}
function makeASpaceship() {
return new vehicles.Spaceship(); // Error: 'vehicles' cannot be used as a value because it was exported using 'export type'.
}
TypeScript 5.0 现可支持使用 extends 字段扩展多个配置文件。这项功能适用于同时管理多个项目,其中“基本”配置文件可由其他 tsconfig.json 文件进行创建和扩展。以往,这项操作只能通过单个文件完成,但现在您可以扩展至多个文件,并在发生字段冲突时以后一个条目为优先。
例如,如果您有一个从 @tsconfig/strictest/tsconfig.json 扩展的基本 sconfig.base.json 文件,则可以让其他 tsconfig.json 文件从这两个文件进一步扩展,如下所示:
{
"extends": ["@tsconfig/strictest/tsconfig.json", "../../../tsconfig.base.json"],
"compilerOptions": {
"outDir": "../lib",
// ...
}
}
这就为多个配置文件的管理带来更大的灵活性,可通过多个文件扩展并轻松控制字段优先级。
TypeScript 5.0 提供多项性能改进,包括更快的对象类型索引和经过优化的条件类型推断。
以上只是 TypeScript 5.0 的部分新功能与改进,请参阅官方公告页面以了解更多详细信息。
参考链接:
https://www.infoq.com/news/2023/03/announcing-TypeScript-5-beta/
https://medium.com/@caopengau/typescript-5-0-a-quick-demo-of-new-features-and-improvements-fbb841728ea