活动公告

系统通知
07-14 23:24
系统通知
通知:本站资源由网友上传分享,如有违规等问题请到版务模块进行投诉,资源失效请在帖子内回复要求补档,会尽快处理!
10-23 09:31

TypeScript 5.0 强势来袭 解析微软最新版本如何通过全新装饰器支持增强类型系统优化编译速度来提升开发者体验与项目维护性

SunJu_FaceMall

3万

主题

3063

科技点

3万

积分

执行版主

碾压王

积分
32876

塔罗立华奏

执行版主 发表于 2025-9-30 00:20:01 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
引言

TypeScript 作为 JavaScript 的超集,自 2012 年由微软发布以来,已经成为了前端开发中不可或缺的工具。它通过添加静态类型定义和其他特性,大大提高了大型项目的可维护性和开发效率。2023 年,微软发布了 TypeScript 5.0,这一版本带来了许多令人兴奋的新特性和改进,包括全新的装饰器支持、增强的类型系统、优化的编译速度等。本文将详细解析 TypeScript 5.0 的这些新特性,以及它们如何提升开发者体验和项目维护性。

TypeScript 5.0 概述

TypeScript 5.0 是 TypeScript 语言的一次重大更新,它不仅带来了一系列新功能,还对现有功能进行了优化和改进。这一版本的主要目标是提高开发者的生产力,使代码更加健壮和可维护,同时提升编译性能。

TypeScript 5.0 的主要新特性包括:

• 全新的装饰器支持(基于 ECMAScript 装饰器提案的第三阶段)
• 增强的类型系统
• 优化的编译速度
• 改进的枚举功能
• 新的工具和实用类型

这些改进共同作用,使得 TypeScript 5.0 成为了一个更加强大和高效的编程语言。

全新装饰器支持

装饰器(Decorators)是一种特殊的声明,可以附加到类声明、方法、访问器、属性或参数上。装饰器使用@expression的形式,其中expression必须是一个函数,它会在运行时被调用,被装饰的声明信息作为参数传入。

在 TypeScript 5.0 之前,装饰器的支持是基于旧版的 ECMAScript 提案,存在一些限制和问题。TypeScript 5.0 采用了 ECMAScript 装饰器提案的第三阶段,带来了更加标准和强大的装饰器功能。

装饰器的基本语法

在 TypeScript 5.0 中,装饰器的定义和使用变得更加简单和直观。下面是一个基本的装饰器示例:
  1. // 定义一个简单的装饰器
  2. function logged(originalMethod: any, context: ClassMethodDecoratorContext) {
  3.     const methodName = String(context.name);
  4.    
  5.     function replacementMethod(this: any, ...args: any[]) {
  6.         console.log(`LOG: Entering method '${methodName}'.`);
  7.         const result = originalMethod.call(this, ...args);
  8.         console.log(`LOG: Exiting method '${methodName}'.`);
  9.         return result;
  10.     }
  11.    
  12.     return replacementMethod;
  13. }
  14. // 使用装饰器
  15. class Person {
  16.     name: string;
  17.     constructor(name: string) {
  18.         this.name = name;
  19.     }
  20.    
  21.     @logged
  22.     greet() {
  23.         console.log(`Hello, my name is ${this.name}.`);
  24.     }
  25. }
  26. const p = new Person("Ron");
  27. p.greet();
  28. // 输出:
  29. // LOG: Entering method 'greet'.
  30. // Hello, my name is Ron.
  31. // LOG: Exiting method 'greet'.
复制代码

在这个例子中,logged是一个方法装饰器,它接收原始方法和上下文作为参数,并返回一个新的方法来替代原始方法。新方法在调用原始方法前后添加了日志记录。

类装饰器

类装饰器用于类声明,可以用来修改、观察或替换类定义。下面是一个类装饰器的示例:
  1. function sealed(constructor: Function, context: ClassDecoratorContext) {
  2.     Object.seal(constructor);
  3.     Object.seal(constructor.prototype);
  4.     console.log(`Sealing the class: ${String(context.name)}`);
  5. }
  6. @sealed
  7. class BugReport {
  8.     type = "report";
  9.     title: string;
  10.    
  11.     constructor(t: string) {
  12.         this.title = t;
  13.     }
  14. }
  15. const bugReport = new BugReport("Needs dark mode");
  16. console.log(bugReport.title); // Needs dark mode
  17. // 尝试添加新属性将会失败
  18. try {
  19.     (bugReport as any).newProp = "test";
  20. } catch (e) {
  21.     console.log(e); // TypeError: Cannot add property newProp, object is not extensible
  22. }
复制代码

在这个例子中,sealed装饰器密封了类及其原型,防止在运行时添加新属性。

属性装饰器

属性装饰器用于类中的属性声明,可以用来修改属性的行为。下面是一个属性装饰器的示例:
  1. function format(formatString: string) {
  2.     return function (originalValue: undefined, context: ClassFieldDecoratorContext) {
  3.         const isPrivate = String(context.name).startsWith('#');
  4.         const propName = isPrivate ? String(context.name).slice(1) : String(context.name);
  5.         
  6.         return function (this: any, value: string) {
  7.             console.log(`Formatting ${propName} with pattern: ${formatString}`);
  8.             return formatString.replace('{0}', value);
  9.         };
  10.     };
  11. }
  12. class Greeter {
  13.     @format('Hello, {0}!')
  14.     greeting: string;
  15.    
  16.     constructor(message: string) {
  17.         this.greeting = message;
  18.     }
  19.    
  20.     greet() {
  21.         console.log(this.greeting);
  22.     }
  23. }
  24. const g = new Greeter('World');
  25. g.greet(); // 输出: Hello, World!
复制代码

在这个例子中,format装饰器工厂返回一个属性装饰器,该装饰器修改属性的设置行为,将值格式化为指定的模式。

参数装饰器

参数装饰器用于类构造函数或方法声明的参数,可以用来修改参数的行为。下面是一个参数装饰器的示例:
  1. function required(originalValue: any, context: ParameterDecoratorContext) {
  2.     const index = context.metadata?.[context.name] ?? [];
  3.     index.push(context.index);
  4.     context.metadata![context.name] = index;
  5. }
  6. function validate(obj: any, context: ClassDecoratorContext) {
  7.     const requiredParams: number[] = context.metadata?.[context.name] ?? [];
  8.    
  9.     for (const index of requiredParams) {
  10.         if (obj[index] === undefined || obj[index] === null) {
  11.             throw new Error(`Parameter at position ${index} is required.`);
  12.         }
  13.     }
  14. }
  15. class User {
  16.     constructor(
  17.         @required public id: number,
  18.         @required public name: string,
  19.         public email?: string
  20.     ) {}
  21.    
  22.     @validate
  23.     static create(...args: any[]) {
  24.         return new User(...args);
  25.     }
  26. }
  27. // 正确使用
  28. const user1 = User.create(1, "John Doe");
  29. console.log(user1); // User { id: 1, name: 'John Doe', email: undefined }
  30. // 错误使用
  31. try {
  32.     const user2 = User.create(1);
  33. } catch (e) {
  34.     console.log(e); // Error: Parameter at position 1 is required.
  35. }
复制代码

在这个例子中,required装饰器标记参数为必需的,validate装饰器检查必需的参数是否提供。

装饰器元数据

TypeScript 5.0 引入了装饰器元数据的概念,允许在装饰器之间共享信息。下面是一个使用装饰器元数据的示例:
  1. // 定义元数据键
  2. const METADATA_KEY = 'design:custom';
  3. // 添加元数据的装饰器
  4. function setMetadata(value: any) {
  5.     return function (target: any, context: ClassDecoratorContext) {
  6.         context.metadata![METADATA_KEY] = value;
  7.     };
  8. }
  9. // 读取元数据的装饰器
  10. function getMetadata(target: any, context: ClassDecoratorContext) {
  11.     const metadata = context.metadata![METADATA_KEY];
  12.     console.log(`Metadata for ${String(context.name)}:`, metadata);
  13. }
  14. @setMetadata({ version: '1.0.0', author: 'TypeScript Team' })
  15. @getMetadata
  16. class Example {
  17.     // ...
  18. }
  19. // 输出: Metadata for Example: { version: '1.0.0', author: 'TypeScript Team' }
复制代码

在这个例子中,setMetadata装饰器设置元数据,getMetadata装饰器读取并打印元数据。

增强的类型系统

TypeScript 5.0 不仅带来了全新的装饰器支持,还对类型系统进行了多项增强,使得类型检查更加精确和灵活。

const类型参数

TypeScript 5.0 引入了const类型参数,允许将泛型参数推断为更具体的字面量类型。这对于需要精确类型信息的函数和 API 特别有用。
  1. // 使用 const 类型参数
  2. function getNames<const T extends readonly string[]>(args: T): T {
  3.     return args;
  4. }
  5. // 在 TypeScript 5.0 之前,返回类型会被推断为 string[]
  6. // 在 TypeScript 5.0 中,返回类型被推断为 readonly ["Alice", "Bob"]
  7. const names = getNames(["Alice", "Bob"] as const);
  8. // 类型为 "Alice" | "Bob"
  9. type NameType = typeof names[number];
复制代码

在这个例子中,const类型参数使得getNames函数能够保留输入数组的精确字面量类型,而不是将其扩展为string[]。

extends支持多种配置类型

TypeScript 5.0 增强了extends关键字的功能,使其能够支持多种配置类型。这对于创建灵活的类型检查和约束非常有用。
  1. // 定义多种配置类型
  2. type Config = {
  3.     db: {
  4.         host: string;
  5.         port: number;
  6.     };
  7.     api: {
  8.         endpoint: string;
  9.         timeout?: number;
  10.     };
  11.     cache?: {
  12.         enabled: boolean;
  13.         ttl?: number;
  14.     };
  15. };
  16. // 使用 extends 检查多种配置
  17. function validateConfig<T extends Config>(config: T): T {
  18.     // 检查必需的配置
  19.     if (!config.db.host || !config.db.port) {
  20.         throw new Error("Database configuration is incomplete");
  21.     }
  22.    
  23.     if (!config.api.endpoint) {
  24.         throw new Error("API configuration is incomplete");
  25.     }
  26.    
  27.     return config;
  28. }
  29. // 正确的配置
  30. const validConfig = validateConfig({
  31.     db: { host: "localhost", port: 5432 },
  32.     api: { endpoint: "https://api.example.com" },
  33.     cache: { enabled: true }
  34. });
  35. // 错误的配置
  36. try {
  37.     const invalidConfig = validateConfig({
  38.         db: { host: "localhost" }, // 缺少 port
  39.         api: { endpoint: "https://api.example.com" }
  40.     });
  41. } catch (e) {
  42.     console.log(e); // Error: Database configuration is incomplete
  43. }
复制代码

在这个例子中,validateConfig函数使用extends关键字来确保输入的配置符合Config类型的结构。

新的实用类型

TypeScript 5.0 引入了一些新的实用类型,使得类型操作更加方便和强大。

satisfies操作符用于验证表达式是否符合某个类型,但不会改变表达式的类型。这对于确保对象符合特定接口,同时保留其精确类型非常有用。
  1. // 定义接口
  2. interface Config {
  3.     host: string;
  4.     port: number;
  5.     ssl?: boolean;
  6. }
  7. // 使用 satisfies 验证对象
  8. const serverConfig = {
  9.     host: "localhost",
  10.     port: 8080,
  11.     ssl: true
  12. } satisfies Config;
  13. // serverConfig 的类型被推断为 { host: string; port: number; ssl: boolean; }
  14. // 而不是 Config
  15. // 错误示例
  16. try {
  17.     const invalidConfig = {
  18.         host: "localhost",
  19.         port: "8080" // port 应该是 number
  20.     } satisfies Config;
  21. } catch (e) {
  22.     console.log(e); // TypeError: Type 'string' is not assignable to type 'number'.
  23. }
复制代码

在这个例子中,satisfies操作符确保serverConfig对象符合Config接口,同时保留了对象的精确类型信息。

TypeScript 5.0 对any类型进行了改进,使其更加安全和可控。现在,当使用any类型时,TypeScript 会提供更明确的警告和建议。
  1. // 使用 any 类型
  2. function processData(data: any): void {
  3.     // 在 TypeScript 5.0 中,这里会有警告
  4.     console.log(data.name); // 可能是 undefined
  5.    
  6.     // 建议使用更具体的类型
  7.     if (data && typeof data === 'object' && 'name' in data) {
  8.         console.log(data.name); // 更安全
  9.     }
  10. }
  11. // 使用 unknown 类型替代 any
  12. function processUnknownData(data: unknown): void {
  13.     // 必须进行类型检查
  14.     if (data && typeof data === 'object' && 'name' in data) {
  15.         console.log((data as { name: string }).name);
  16.     }
  17. }
复制代码

在这个例子中,TypeScript 5.0 对any类型的使用提供了更明确的警告,并建议使用更具体的类型或unknown类型。

优化编译速度

TypeScript 5.0 对编译性能进行了显著优化,使得大型项目的构建速度大幅提升。这些优化包括改进的增量编译、更高效的内存使用和更好的并行处理。

增量编译的改进

TypeScript 5.0 改进了增量编译机制,使得在修改文件后,只有受影响的文件才会被重新编译。这对于大型项目来说,可以显著减少编译时间。
  1. // tsconfig.json
  2. {
  3.     "compilerOptions": {
  4.         "target": "es2020",
  5.         "module": "commonjs",
  6.         "outDir": "./dist",
  7.         "rootDir": "./src",
  8.         "strict": true,
  9.         "incremental": true, // 启用增量编译
  10.         "tsBuildInfoFile": "./dist/.tsbuildinfo" // 指定增量编译信息文件
  11.     },
  12.     "include": ["src/**/*"]
  13. }
复制代码

在这个tsconfig.json配置中,incremental选项启用了增量编译,tsBuildInfoFile指定了存储增量编译信息的文件。当项目被重新编译时,TypeScript 会使用这些信息来确定哪些文件需要重新编译。

内存使用的优化

TypeScript 5.0 优化了内存使用,减少了编译过程中的内存占用。这对于大型项目来说,可以减少内存压力,提高编译性能。
  1. // 大型项目示例
  2. // 在 TypeScript 5.0 之前,编译这个项目可能会占用大量内存
  3. // 在 TypeScript 5.0 中,内存使用得到了优化
  4. // src/large-module.ts
  5. export const largeDataSet = Array(1000000).fill(0).map((_, i) => ({
  6.     id: i,
  7.     name: `Item ${i}`,
  8.     value: Math.random() * 1000
  9. }));
  10. export function processLargeData() {
  11.     // 处理大型数据集
  12.     return largeDataSet.filter(item => item.value > 500);
  13. }
  14. // src/index.ts
  15. import { processLargeData } from './large-module';
  16. console.log(processLargeData().length);
复制代码

在这个例子中,即使处理大型数据集,TypeScript 5.0 也能够有效地管理内存使用,避免内存溢出或性能下降。

并行处理的改进

TypeScript 5.0 改进了并行处理能力,使得在多核处理器上能够更高效地编译项目。这对于大型项目来说,可以显著减少编译时间。
  1. // tsconfig.json
  2. {
  3.     "compilerOptions": {
  4.         "target": "es2020",
  5.         "module": "commonjs",
  6.         "outDir": "./dist",
  7.         "rootDir": "./src",
  8.         "strict": true,
  9.         "incremental": true,
  10.         "tsBuildInfoFile": "./dist/.tsbuildinfo"
  11.     },
  12.     "include": ["src/**/*"],
  13.     "references": [ // 使用项目引用实现并行编译
  14.         { "path": "./src/core" },
  15.         { "path": "./src/utils" },
  16.         { "path": "./src/components" }
  17.     ]
  18. }
复制代码

在这个tsconfig.json配置中,references选项定义了项目引用,允许 TypeScript 并行编译不同的项目部分。这在大型项目中特别有用,可以将项目分解为多个子项目,并行编译以提高效率。

提升开发者体验

TypeScript 5.0 的新特性和改进不仅提高了代码的类型安全性和性能,还显著提升了开发者的体验。这些改进包括更好的错误信息、增强的编辑器支持和更直观的 API 设计。

更好的错误信息

TypeScript 5.0 提供了更详细和有用的错误信息,帮助开发者更快地定位和解决问题。
  1. // 示例:更详细的错误信息
  2. interface User {
  3.     id: number;
  4.     name: string;
  5.     email: string;
  6. }
  7. function getUser(id: number): User {
  8.     // 假设这是一个从 API 获取用户的函数
  9.     return { id, name: "John Doe" }; // 缺少 email 属性
  10. }
  11. // 在 TypeScript 5.0 中,错误信息更加详细
  12. // 之前:Property 'email' is missing in type '{ id: number; name: string; }' but required in type 'User'.
  13. // 现在:Property 'email' is missing in type '{ id: number; name: string; }' but required in type 'User'.
  14. // The expected type is coming from the return type of this function.
  15. const user = getUser(1);
复制代码

在这个例子中,TypeScript 5.0 提供了更详细的错误信息,明确指出错误来自函数的返回类型,帮助开发者更快地定位问题。

增强的编辑器支持

TypeScript 5.0 增强了编辑器支持,提供了更好的代码补全、类型提示和重构功能。这些改进使得开发者能够更高效地编写和维护代码。
  1. // 示例:增强的代码补全
  2. interface ApiResponse<T> {
  3.     data: T;
  4.     status: number;
  5.     message: string;
  6. }
  7. interface User {
  8.     id: number;
  9.     name: string;
  10.     email: string;
  11. }
  12. // 在编辑器中,当输入 response. 时,TypeScript 5.0 会提供更智能的代码补全
  13. function handleResponse(response: ApiResponse<User>) {
  14.     // 输入 response. 后,编辑器会提示 data, status, message
  15.     // 选择 data 后,编辑器会进一步提示 id, name, email
  16.     console.log(response.data.name);
  17. }
复制代码

在这个例子中,TypeScript 5.0 提供了更智能的代码补全,帮助开发者更快地编写代码,减少错误。

更直观的 API 设计

TypeScript 5.0 的新特性使得 API 设计更加直观和易用。特别是装饰器和增强的类型系统,使得创建和使用 API 变得更加简单和直观。
  1. // 示例:使用装饰器创建直观的 API
  2. class APIClient {
  3.     private baseURL: string;
  4.    
  5.     constructor(baseURL: string) {
  6.         this.baseURL = baseURL;
  7.     }
  8.    
  9.     @logAPICall
  10.     async getUser(id: number): Promise<User> {
  11.         const response = await fetch(`${this.baseURL}/users/${id}`);
  12.         return response.json();
  13.     }
  14.    
  15.     @logAPICall
  16.     @validateParams
  17.     async updateUser(id: number, data: Partial<User>): Promise<User> {
  18.         const response = await fetch(`${this.baseURL}/users/${id}`, {
  19.             method: 'PUT',
  20.             headers: {
  21.                 'Content-Type': 'application/json',
  22.             },
  23.             body: JSON.stringify(data),
  24.         });
  25.         return response.json();
  26.     }
  27. }
  28. // 使用 API
  29. const api = new APIClient('https://api.example.com');
  30. // 编辑器会提供完整的类型提示和参数验证
  31. const user = await api.getUser(1);
  32. const updatedUser = await api.updateUser(1, { name: "Jane Doe" });
复制代码

在这个例子中,装饰器使得 API 的实现更加直观和易用,同时提供了完整的类型提示和参数验证,提高了开发效率和代码质量。

提升项目维护性

TypeScript 5.0 的新特性和改进不仅提高了开发效率,还显著提升了项目的可维护性。这些改进包括更好的代码组织、更强的类型安全和更清晰的代码结构。

更好的代码组织

TypeScript 5.0 的装饰器和模块系统改进使得代码组织更加清晰和模块化。这对于大型项目的维护来说至关重要。
  1. // 示例:使用装饰器组织代码
  2. // decorators/validation.ts
  3. export function validate(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
  4.     const originalMethod = descriptor.value;
  5.    
  6.     descriptor.value = function(...args: any[]) {
  7.         // 验证逻辑
  8.         for (const arg of args) {
  9.             if (arg === null || arg === undefined) {
  10.                 throw new Error(`Invalid argument: ${arg}`);
  11.             }
  12.         }
  13.         
  14.         return originalMethod.apply(this, args);
  15.     };
  16.    
  17.     return descriptor;
  18. }
  19. // decorators/logging.ts
  20. export function log(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
  21.     const originalMethod = descriptor.value;
  22.    
  23.     descriptor.value = function(...args: any[]) {
  24.         console.log(`Calling ${propertyKey} with args: ${JSON.stringify(args)}`);
  25.         const result = originalMethod.apply(this, args);
  26.         console.log(`Method ${propertyKey} returned: ${JSON.stringify(result)}`);
  27.         return result;
  28.     };
  29.    
  30.     return descriptor;
  31. }
  32. // services/user.service.ts
  33. import { validate } from '../decorators/validation';
  34. import { log } from '../decorators/logging';
  35. export class UserService {
  36.     @log
  37.     @validate
  38.     getUser(id: number): User | null {
  39.         // 获取用户逻辑
  40.         return { id, name: "John Doe", email: "john@example.com" };
  41.     }
  42.    
  43.     @log
  44.     @validate
  45.     updateUser(id: number, data: Partial<User>): User {
  46.         // 更新用户逻辑
  47.         return { id, ...data, email: "john@example.com" };
  48.     }
  49. }
复制代码

在这个例子中,装饰器使得代码组织更加清晰和模块化,每个装饰器负责特定的功能,使得代码更易于理解和维护。

更强的类型安全

TypeScript 5.0 增强的类型系统提供了更强的类型安全,减少了运行时错误的可能性。这对于项目的长期维护来说至关重要。
  1. // 示例:增强的类型安全
  2. // types/database.ts
  3. export interface DatabaseConfig {
  4.     host: string;
  5.     port: number;
  6.     username: string;
  7.     password: string;
  8.     database: string;
  9. }
  10. // types/api.ts
  11. export interface APIConfig {
  12.     endpoint: string;
  13.     timeout: number;
  14.     retries: number;
  15. }
  16. // types/app.ts
  17. export interface AppConfig {
  18.     database: DatabaseConfig;
  19.     api: APIConfig;
  20.     debug: boolean;
  21. }
  22. // utils/config-validator.ts
  23. import { AppConfig } from '../types/app';
  24. export function validateConfig(config: unknown): AppConfig {
  25.     if (typeof config !== 'object' || config === null) {
  26.         throw new Error('Config must be an object');
  27.     }
  28.    
  29.     const { database, api, debug } = config as Partial<AppConfig>;
  30.    
  31.     // 验证数据库配置
  32.     if (!database || typeof database !== 'object') {
  33.         throw new Error('Database config is required');
  34.     }
  35.    
  36.     if (typeof database.host !== 'string' ||
  37.         typeof database.port !== 'number' ||
  38.         typeof database.username !== 'string' ||
  39.         typeof database.password !== 'string' ||
  40.         typeof database.database !== 'string') {
  41.         throw new Error('Invalid database config');
  42.     }
  43.    
  44.     // 验证 API 配置
  45.     if (!api || typeof api !== 'object') {
  46.         throw new Error('API config is required');
  47.     }
  48.    
  49.     if (typeof api.endpoint !== 'string' ||
  50.         typeof api.timeout !== 'number' ||
  51.         typeof api.retries !== 'number') {
  52.         throw new Error('Invalid API config');
  53.     }
  54.    
  55.     // 验证调试标志
  56.     if (typeof debug !== 'boolean') {
  57.         throw new Error('Debug flag must be a boolean');
  58.     }
  59.    
  60.     return config as AppConfig;
  61. }
  62. // app.ts
  63. import { validateConfig } from './utils/config-validator';
  64. const config = {
  65.     database: {
  66.         host: "localhost",
  67.         port: 5432,
  68.         username: "admin",
  69.         password: "password",
  70.         database: "myapp"
  71.     },
  72.     api: {
  73.         endpoint: "https://api.example.com",
  74.         timeout: 5000,
  75.         retries: 3
  76.     },
  77.     debug: true
  78. };
  79. // 验证配置
  80. const validatedConfig = validateConfig(config);
  81. console.log('Config is valid:', validatedConfig);
复制代码

在这个例子中,TypeScript 5.0 的增强类型系统使得配置验证更加严格和安全,减少了运行时错误的可能性。

更清晰的代码结构

TypeScript 5.0 的新特性使得代码结构更加清晰和直观。这对于项目的长期维护来说至关重要,特别是对于新加入团队的成员。
  1. // 示例:清晰的代码结构
  2. // entities/user.entity.ts
  3. export class User {
  4.     constructor(
  5.         public id: number,
  6.         public name: string,
  7.         public email: string,
  8.         public createdAt: Date = new Date(),
  9.         public updatedAt: Date = new Date()
  10.     ) {}
  11.    
  12.     @validateEmail
  13.     setEmail(email: string): void {
  14.         this.email = email;
  15.         this.updatedAt = new Date();
  16.     }
  17.    
  18.     @logChange
  19.     setName(name: string): void {
  20.         this.name = name;
  21.         this.updatedAt = new Date();
  22.     }
  23. }
  24. // repositories/user.repository.ts
  25. export class UserRepository {
  26.     constructor(private db: Database) {}
  27.    
  28.     async findById(id: number): Promise<User | null> {
  29.         const row = await this.db.query('SELECT * FROM users WHERE id = ?', [id]);
  30.         return row ? new User(row.id, row.name, row.email, row.created_at, row.updated_at) : null;
  31.     }
  32.    
  33.     async save(user: User): Promise<User> {
  34.         if (user.id) {
  35.             // 更新现有用户
  36.             await this.db.query(
  37.                 'UPDATE users SET name = ?, email = ?, updated_at = ? WHERE id = ?',
  38.                 [user.name, user.email, user.updatedAt, user.id]
  39.             );
  40.         } else {
  41.             // 创建新用户
  42.             const result = await this.db.query(
  43.                 'INSERT INTO users (name, email, created_at, updated_at) VALUES (?, ?, ?, ?)',
  44.                 [user.name, user.email, user.createdAt, user.updatedAt]
  45.             );
  46.             user.id = result.insertId;
  47.         }
  48.         
  49.         return user;
  50.     }
  51. }
  52. // services/user.service.ts
  53. export class UserService {
  54.     constructor(private userRepository: UserRepository) {}
  55.    
  56.     async getUser(id: number): Promise<User | null> {
  57.         return this.userRepository.findById(id);
  58.     }
  59.    
  60.     async createUser(userData: Omit<User, 'id' | 'createdAt' | 'updatedAt'>): Promise<User> {
  61.         const user = new User(0, userData.name, userData.email);
  62.         return this.userRepository.save(user);
  63.     }
  64.    
  65.     async updateUser(id: number, userData: Partial<Omit<User, 'id' | 'createdAt' | 'updatedAt'>>): Promise<User | null> {
  66.         const user = await this.userRepository.findById(id);
  67.         
  68.         if (!user) {
  69.             return null;
  70.         }
  71.         
  72.         if (userData.name) {
  73.             user.setName(userData.name);
  74.         }
  75.         
  76.         if (userData.email) {
  77.             user.setEmail(userData.email);
  78.         }
  79.         
  80.         return this.userRepository.save(user);
  81.     }
  82. }
  83. // controllers/user.controller.ts
  84. export class UserController {
  85.     constructor(private userService: UserService) {}
  86.    
  87.     async getUser(req: Request, res: Response): Promise<void> {
  88.         const id = parseInt(req.params.id);
  89.         
  90.         if (isNaN(id)) {
  91.             res.status(400).json({ error: 'Invalid user ID' });
  92.             return;
  93.         }
  94.         
  95.         const user = await this.userService.getUser(id);
  96.         
  97.         if (!user) {
  98.             res.status(404).json({ error: 'User not found' });
  99.             return;
  100.         }
  101.         
  102.         res.json(user);
  103.     }
  104.    
  105.     async createUser(req: Request, res: Response): Promise<void> {
  106.         const { name, email } = req.body;
  107.         
  108.         if (!name || !email) {
  109.             res.status(400).json({ error: 'Name and email are required' });
  110.             return;
  111.         }
  112.         
  113.         try {
  114.             const user = await this.userService.createUser({ name, email });
  115.             res.status(201).json(user);
  116.         } catch (error) {
  117.             res.status(500).json({ error: 'Failed to create user' });
  118.         }
  119.     }
  120.    
  121.     async updateUser(req: Request, res: Response): Promise<void> {
  122.         const id = parseInt(req.params.id);
  123.         
  124.         if (isNaN(id)) {
  125.             res.status(400).json({ error: 'Invalid user ID' });
  126.             return;
  127.         }
  128.         
  129.         const { name, email } = req.body;
  130.         
  131.         try {
  132.             const user = await this.userService.updateUser(id, { name, email });
  133.             
  134.             if (!user) {
  135.                 res.status(404).json({ error: 'User not found' });
  136.                 return;
  137.             }
  138.             
  139.             res.json(user);
  140.         } catch (error) {
  141.             res.status(500).json({ error: 'Failed to update user' });
  142.         }
  143.     }
  144. }
复制代码

在这个例子中,代码结构非常清晰,每个类和模块都有明确的职责,使得代码更易于理解和维护。装饰器的使用使得横切关注点(如验证和日志记录)的实现更加清晰和模块化。

结论

TypeScript 5.0 是一次重大的更新,它通过全新的装饰器支持、增强的类型系统和优化的编译速度,显著提升了开发者体验和项目维护性。

全新的装饰器支持基于 ECMAScript 装饰器提案的第三阶段,提供了更加标准和强大的装饰器功能,使得代码更加模块化和可维护。增强的类型系统,如const类型参数、extends支持多种配置类型和新的实用类型,使得类型检查更加精确和灵活。优化的编译速度,包括改进的增量编译、更高效的内存使用和更好的并行处理,使得大型项目的构建速度大幅提升。

这些改进共同作用,使得 TypeScript 5.0 成为了一个更加强大和高效的编程语言,为开发者提供了更好的工具来构建和维护大型项目。无论是新项目还是现有项目,升级到 TypeScript 5.0 都将带来显著的好处,包括更高的开发效率、更好的代码质量和更强的可维护性。

随着 TypeScript 的不断发展,我们可以期待更多的创新和改进,使得前端开发变得更加高效和愉快。TypeScript 5.0 是这一进程中的重要一步,它展示了微软对 TypeScript 的持续投入和对开发者需求的深刻理解。
「七転び八起き(ななころびやおき)」
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则