探索最令人兴奋的功能和更新
作为一种不断发展的编程语言,TypeScript 带来了大量的改进和新功能。在本文中,我们将深入探讨 TypeScript 的最新版本 5.0,并探索其最值得关注的更新。
1. 装饰器
TypeScript 5.0 引入了一个重新设计的装饰器系统,改进了类型检查和元数据生成。装饰器现在更加无缝地与类型系统配合,使您能够编写更干净、更健壮的代码。以下是一个简单的方法装饰器的示例:
function log<This, Args extends any[], Return>( target: (this: This, ...args: Args) => Return, context: ClassMethodDecoratorContext< This, (this: This, ...args: Args) => Return > ) { const methodName = String(context.name); function replacementMethod(this: This, ...args: Args): Return { console.log(`LOG: Entering method '${methodName}'.`); const result = target.call(this, ...args); console.log(`LOG: Exiting method '${methodName}'.`); return result; } return replacementMethod; } class Calculator { @log add(a: number, b: number): number { return a + b; } } const calculator = new Calculator(); console.log(calculator.add(2, 3)); // "LOG: Entering method 'add'." // "LOG: Exiting method 'add'." // 5
在这个例子中,@log 装饰器在每次调用方法时记录方法名。除了方法装饰器,TypeScript 5.0 还支持自动访问器装饰器、getter 和 setter 装饰器等。您可以在这个快速指南中了解更多:
TypeScript 5.0 装饰器快速指南
使用装饰器扩展您的 TypeScript 5.0 工具包
2. const 类型参数
在 TypeScript 5.0 之前,它的推断通常会选择更一般的类型,例如将 ["Alice", "Bob", "Eve"] 推断为 string[],如果您想要更具体的类型,则必须为其添加 as const:
// string[] const a = ["Alice", "Bob", "Eve"] // readonly ["Alice", "Bob", "Eve"] const b = ["Alice", "Bob", "Eve"] as const
而 TypeScript 5.0 允许您在类型参数声明中添加 const 修饰符:
declare function fnGood<const T extends readonly string[]>(args: T): void; // T is readonly ["a", "b", "c"] fnGood(["a", "b" ,"c"]);
但请记住,const 修饰符仅影响在调用中编写的对象、数组和原始表达式的推断,因此无法(或无法)通过 as const 修改的参数不会看到任何行为上的变化:
declare function fnGood<const T extends readonly string[]>(args: T): void; const arr = ["a", "b" ,"c"]; // 'T' is still 'string[]'-- the 'const' modifier has no effect here fnGood(arr);
3. 支持在 extends 中使用多个配置文件
TypeScript 5.0 可以在您的 tsconfig.json 中扩展多个配置文件。此功能使得在项目之间共享和管理配置更加容易。以下是如何使用多个配置文件的示例:
{ "extends": ["./config/base", "./config/jest"], "compilerOptions": { "target": "esnext", "module": "commonjs", "strict": true } }
在这个例子中,配置文件扩展了 base 和 jest 配置,允许您根据需要组合和覆盖设置。
4. 所有枚举都是联合枚举
在 TypeScript 5.0 中,所有枚举现在都被视为联合枚举。联合枚举提供了更好的类型安全性和更好的人机工程学,以处理枚举值。以下是一个示例:
enum E { A = 10 * 10, // Numeric literal enum member B = 'foo', // String literal enum member C = Math.random(), // Opaque computed enum member } function getStringValue(e: E): string { return String(e); } const val = getStringValue(E.A); // "100"
TypeScript 5.0 通过为每个计算成员创建唯一类型来将所有枚举转换为联合枚举。这意味着现在所有枚举都可以被缩小并且其成员也可以被引用为类型。
5. — moduleResolution bundler
TypeScript 5.0 引入了一个名为 bundler 的新模块解析策略。这个策略旨在与打包程序(如 Webpack 和 Rollup)配合使用,从而实现更高效、更流畅的构建过程(就像过去在 Node.js 模块中的任何相对导入都需要包括文件扩展名一样)。 要启用 bundler 模块解析策略,请在 tsconfig.json 中使用以下配置:
{ "compilerOptions": { "moduleResolution": "bundler" } }
6. 解析自定义标志
TypeScript 5.0 添加了几个新标志来自定义模块解析过程。这些标志提供了更细粒度的控制,以控制模块是如何解析的,使您能够微调构建过程。以下是一个简要概述:
--allowImportingTsExtensions:允许导入带有 TypeScript 特定扩展名(如 .ts、.mts 或 .tsx)的 TypeScript 文件。
--resolvePackageJsonExports:强制 TypeScript 在从 node_modules 中的包中读取时,查看 package.json 文件的 exports 字段。
--resolvePackageJsonImports:强制 TypeScript 在从以 # 开头的查找开始时,查看 package.json 文件的 imports 字段。
--allowArbitraryExtensions:允许通过查找以 {file basename}.d.{extension}.ts 格式的声明文件来导入具有未知扩展名的文件。
--customConditions:在 TypeScript 从 package.json 的 exports 或 imports 字段解析时,采用额外的条件列表。
7. --verbatimModuleSyntax
TypeScript 5.0 中的新 --verbatimModuleSyntax 标志允许您在发出 JavaScript 代码时保留原始模块语法。这个特性在与打包程序一起工作时特别有用,因为它可以防止需要额外的转换。例如:
// Erased away entirely. import type { A } from "a"; // Rewritten to 'import { b } from "bcd";' import { b, type c, type d } from "bcd"; // Rewritten to 'import {} from "xyz";' import { type xyz } from "xyz";
要启用此标志,请将其添加到您的 tsconfig.json:
{ "compilerOptions": { "verbatimModuleSyntax": true } }
8. 支持 export type *
TypeScript 5.0 引入了对 export type * 语法的支持,允许您重新导出另一个模块中的所有类型。这种语法特别适用于创建仅包含类型的模块或聚合来自多个源的类型。以下是一个示例:
// types.ts export type { Foo } from './foo'; export type { Bar } from './bar'; // index.ts export type * from './types'; // Also support export type * as Types from './types';
在这个例子中,index.ts 模块使用 export type * 语法重新导出了 types.ts 模块中的所有类型。
9. JSDoc 中的 @satisfies 支持
TypeScript 5.0 中的新 @satisfies JSDoc 标签使您能够指定函数实现满足特定接口。这个特性在使用结构类型或使用 TypeScript 对 JavaScript 代码进行类型检查时特别有用。以下是一个示例:
// interface Greeter { // greet(name: string): number; // } /** * @typedef {Function} Greeter * @param {string} name * @returns {string} */ /** * @satisfies {Greeter} */ function greeter(name: string) { return `Hello, ${name}!`; }
在这个例子中,greeter 函数带有 @satisfies JSDoc 标签,表示它满足 Greeter 接口。