0

0

理解 TypeScript 中的装饰器:第一原理方法

心靈之曲

心靈之曲

发布时间:2024-09-21 09:48:10

|

1185人浏览过

|

来源于dev.to

转载

理解 typescript 中的装饰器:第一原理方法

typescript 中的装饰器提供了一种强大的机制来修改类、方法、属性和参数的行为。虽然它们看起来像是一种现代的便利,但装饰器植根于面向对象编程中成熟的装饰器模式。通过抽象日志记录、验证或访问控制等常见功能,装饰器允许开发人员编写更清晰、更易于维护的代码。

在本文中,我们将从首要原则探索装饰器,分解其核心功能,并从头开始实现它们。在此过程中,我们将了解一些实际应用程序,这些应用程序展示了装饰器在日常 typescript 开发中的实用性。

什么是装饰器?

在 typescript 中,装饰器只是一个可以附加到类、方法、属性或参数的函数。此函数在设计时执行,使您能够在代码运行之前更改代码的行为或结构。装饰器支持元编程,允许我们在不修改原始逻辑的情况下添加额外的功能。

让我们从一个方法装饰器的简单示例开始,该示例记录调用方法的时间:

function log(target: any, propertykey: string, descriptor: propertydescriptor) {
  const originalmethod = descriptor.value;

  descriptor.value = function (...args: any[]) {
    console.log(`calling ${propertykey} with arguments: ${args}`);
    return originalmethod.apply(this, args);
  };

  return descriptor;
}

class example {
  @log
  greet(name: string) {
    return `hello, ${name}`;
  }
}

const example = new example();
example.greet('john');

这里,日志装饰器包装了greet方法,在执行之前记录其调用和参数。此模式对于将日志记录等横切关注点与核心逻辑分离非常有用。

装饰器如何工作

typescript 中的装饰器是接受与其所装饰的项目相关的元数据的函数。基于这些元数据(如类原型、方法名称或属性描述符),装饰器可以修改行为甚至替换被装饰的对象。

装饰器的类型

装饰器可以应用于各种目标,每个目标都有不同的目的:

  • 类装饰器:接收类构造函数的函数。
function classdecorator(constructor: function) {
  // modify or extend the class constructor or prototype
}
  • 方法装饰器:接收目标对象、方法名称和方法描述符的函数。
function methoddecorator(target: any, propertykey: string, descriptor: propertydescriptor) {
  // modify the method's descriptor
}
  • 属性装饰器:接收目标对象和属性名称的函数。
function propertydecorator(target: any, propertykey: string) {
  // modify the behavior of the property
}
  • 参数装饰器:接收目标、方法名称和参数索引的函数。
function parameterdecorator(target: any, propertykey: string, parameterindex: number) {
  // modify or inspect the method's parameter
}

将参数传递给装饰器

装饰器最强大的功能之一是它们接受参数的能力,允许您自定义它们的行为。例如,让我们创建一个方法装饰器,它根据参数有条件地记录方法调用。

function logconditionally(shouldlog: boolean) {
  return function (target: any, propertykey: string, descriptor: propertydescriptor) {
    const originalmethod = descriptor.value;

    descriptor.value = function (...args: any[]) {
      if (shouldlog) {
        console.log(`calling ${propertykey} with arguments: ${args}`);
      }
      return originalmethod.apply(this, args);
    };

    return descriptor;
  };
}

class example {
  @logconditionally(true)
  greet(name: string) {
    return `hello, ${name}`;
  }
}

const example = new example();
example.greet('typescript developer');

通过将 true 传递给 logconditionally 装饰器,我们确保该方法记录其执行情况。如果我们传递 false,则跳过日志记录。这种灵活性是使装饰器具有多功能性和可重用性的关键。

装饰器的实际应用

装饰器在许多库和框架中都有实际用途。以下是一些值得注意的示例,说明了装饰器如何简化复杂的功能:

Cursor
Cursor

一个新的IDE,使用AI来帮助您重构、理解、调试和编写代码。

下载
  • 类验证器中的验证:在数据驱动的应用程序中,验证至关重要。 class-validator 包使用装饰器来简化验证 typescript 类中字段的过程。
import { isemail, isnotempty } from 'class-validator';

class user {
  @isnotempty()
  name: string;

  @isemail()
  email: string;
}

在此示例中,@isemail 和 @isnotempty 装饰器确保电子邮件字段是有效的电子邮件地址并且名称字段不为空。这些装饰器消除了手动验证逻辑的需要,从而节省了时间。

  • 使用 typeorm 进行对象关系映射:装饰器广泛用于 typeorm 等 orm 框架中,用于将 typescript 类映射到数据库表。此映射是使用装饰器以声明方式完成的。
import { entity, column, primarygeneratedcolumn } from 'typeorm';

@entity()
class user {
  @primarygeneratedcolumn()
  id: number;

  @column()
  name: string;

  @column()
  email: string;
}

这里,@entity、@column 和 @primarygeneeratedcolumn 定义了 user 表的结构。这些装饰器抽象了 sql 表创建的复杂性,使代码更具可读性和可维护性。

  • angular 依赖注入:在 angular 中,装饰器在管理服务和组件方面发挥着关键作用。 @injectable 装饰器将一个类标记为可以注入其他组件或服务的服务。
@injectable({
  providedin: 'root',
})
class userservice {
  constructor(private http: httpclient) {}
}

在这种情况下,@injectable 装饰器向 angular 的依赖注入系统发出信号,表明应在全局范围内提供 userservice。这允许跨应用程序无缝集成服务。

实现你自己的装饰器:分解

装饰器的核心就是函数。让我们分解一下从头开始创建装饰器的过程:

类装饰器

类装饰器接收类的构造函数,可以用来修改类原型,甚至替换构造函数。

function addtimestamp(constructor: function) {
  constructor.prototype.timestamp = new date();
}

@addtimestamp
class myclass {
  id: number;
  constructor(id: number) {
    this.id = id;
  }
}

const instance = new myclass(1);
console.log(instance.timestamp);  // outputs the current timestamp

方法装饰器

方法装饰器修改方法描述符,允许您更改方法本身的行为。

function logexecutiontime(target: any, propertykey: string, descriptor: propertydescriptor) {
  const originalmethod = descriptor.value;

  descriptor.value = function (...args: any[]) {
    const start = performance.now();
    const result = originalmethod.apply(this, args);
    const end = performance.now();
    console.log(`${propertykey} executed in ${end - start}ms`);
    return result;
  };

  return descriptor;
}

class service {
  @logexecutiontime
  execute() {
    // simulate work
    for (let i = 0; i < 1e6; i++) {}
  }
}

const service = new service();
service.execute();  // logs the execution time

物业装修师

属性装饰器允许您拦截属性访问和修改,这对于跟踪更改非常有用。

function trackChanges(target: any, propertyKey: string) {
  let value = target[propertyKey];

  const getter = () => value;
  const setter = (newValue: any) => {
    console.log(`${propertyKey} changed from ${value} to ${newValue}`);
    value = newValue;
  };

  Object.defineProperty(target, propertyKey, {
    get: getter,
    set: setter,
  });
}

class Product {
  @trackChanges
  price: number;

  constructor(price: number) {
    this.price = price;
  }
}

const product = new Product(100);
product.price = 200;  // Logs the change

结论

typescript 中的装饰器允许您以干净、声明的方式抽象和重用功能。无论您使用验证、orm 还是依赖注入,装饰器都有助于减少样板文件并保持代码模块化和可维护性。从第一原理出发了解它们的工作原理可以更轻松地充分利用它们的潜力并根据您的应用程序定制解决方案。

通过更深入地了解装饰器的结构和实际应用,您现在已经了解了它们如何简化复杂的编码任务并简化各个领域的代码。

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
TypeScript工程化开发与Vite构建优化实践
TypeScript工程化开发与Vite构建优化实践

本专题面向前端开发者,深入讲解 TypeScript 类型系统与大型项目结构设计方法,并结合 Vite 构建工具优化前端工程化流程。内容包括模块化设计、类型声明管理、代码分割、热更新原理以及构建性能调优。通过完整项目示例,帮助开发者提升代码可维护性与开发效率。

49

2026.02.13

TypeScript全栈项目架构与接口规范设计
TypeScript全栈项目架构与接口规范设计

本专题面向全栈开发者,系统讲解基于 TypeScript 构建前后端统一技术栈的工程化实践。内容涵盖项目分层设计、接口协议规范、类型共享机制、错误码体系设计、接口自动化生成与文档维护方案。通过完整项目示例,帮助开发者构建结构清晰、类型安全、易维护的现代全栈应用架构。

196

2026.02.25

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

37

2026.03.13

数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

1134

2023.10.12

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

340

2023.10.27

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

381

2024.02.23

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

2194

2024.03.06

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

380

2024.03.06

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

26

2026.03.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号