TypeScript 装饰器都有那些应用场景?如何更快的上手?
TypeScript 装饰器简介
在 TypeScript 中,装饰器(Decorators)是一种特殊的语法,用于在类、类方法、属性、访问器等上动态地添加行为或修改现有行为。装饰器可以用来增强类的功能、修改方法的行为,或者修改类的元数据等。它们通常用于元编程和 AOP(面向切面编程)等场景。
装饰器在 TypeScript 中的实现基于 ECMAScript 提案的实验性特性,但目前 TypeScript 已经支持了装饰器的编写和使用。需要注意的是,装饰器特性必须通过 experimentalDecorators
编译选项开启。
开启装饰器支持
在 tsconfig.json
中配置:
{"compilerOptions": {"experimentalDecorators": true}
}
装饰器的类型
装饰器可以应用于以下几种目标:
- 类装饰器 (Class Decorators):应用于类构造函数,修改类的行为或元数据。
- 方法装饰器 (Method Decorators):应用于类的方法,允许修改方法的属性或行为。
- 属性装饰器 (Property Decorators):应用于类的属性,用于修改或定义属性的元数据。
- 访问器装饰器 (Accessor Decorators):应用于类的 getter 或 setter 方法。
- 参数装饰器 (Parameter Decorators):应用于方法参数,主要用于修改或注入方法参数的元数据。
装饰器的应用场景
装饰器常用于以下几个场景:
- 类的功能增强:如注入依赖、日志记录、权限校验等。
- 方法行为修改:例如,控制方法的执行、缓存机制、性能监控等。
- 自动化注入:在一些框架中,装饰器用来自动注入依赖,比如 Angular 中的服务注入。
- 性能分析和日志:自动记录函数的调用时间、参数等。
示例:使用装饰器的实际场景
假设我们有一个项目需要记录方法调用的日志,并且需要验证用户是否有权限执行某些操作。我们可以使用装饰器来实现这些功能。
1. 类装饰器
类装饰器通常用于增强类的行为,比如记录日志、依赖注入等。
function Logger(constructor: Function) {console.log(`Class ${constructor.name} is instantiated.`);
}@Logger
class UserService {constructor() {console.log("UserService instance created.");}
}const userService = new UserService();
解释:Logger
装饰器会在类实例化时打印出该类的名称。在 @Logger
之后,当 UserService
被实例化时,控制台输出 Class UserService is instantiated.
。
2. 方法装饰器
方法装饰器可以修改方法的行为或添加额外的功能。我们可以使用方法装饰器来记录日志,验证权限等。
function Log(target: any, propertyName: string, descriptor: PropertyDescriptor) {const originalMethod = descriptor.value;descriptor.value = function (...args: any[]) {console.log(`Method ${propertyName} is called with args: ${args}`);return originalMethod.apply(this, args);};
}class UserService {@LoggetUser(userId: number) {console.log(`Fetching user with ID: ${userId}`);}
}const userService = new UserService();
userService.getUser(42);
解释:@Log
装饰器会修改 getUser
方法,在调用该方法时记录日志,打印出方法名和传入的参数。输出结果为:
Method getUser is called with args: [42]
Fetching user with ID: 42
3. 属性装饰器
属性装饰器可以用来修改类的属性行为或元数据。例如,我们可以用它来设置字段的可访问性或记录日志。
function Observable(target: any, propertyName: string) {let value = target[propertyName];const getter = () => {console.log(`Getting value of ${propertyName}: ${value}`);return value;};const setter = (newVal: any) => {console.log(`Setting value of ${propertyName} to: ${newVal}`);value = newVal;};Object.defineProperty(target, propertyName, {get: getter,set: setter,});
}class User {@Observablename: string;constructor(name: string) {this.name = name;}
}const user = new User("Alice");
user.name = "Bob"; // Console logs: Setting value of name to: Bob
console.log(user.name); // Console logs: Getting value of name: Bob
解释:@Observable
装饰器为 name
属性创建了 getter 和 setter 方法,控制属性的访问并记录相关日志。
4. 权限校验的实际应用
装饰器常用于权限校验等场景,检查用户是否有权限执行某个方法。例如:
function PermissionRequired(permission: string) {return function (target: any, propertyName: string, descriptor: PropertyDescriptor) {const originalMethod = descriptor.value;descriptor.value = function (...args: any[]) {const userPermissions = ["READ", "WRITE"]; // 假设的用户权限if (!userPermissions.includes(permission)) {console.log(`Permission denied. Missing permission: ${permission}`);return;}return originalMethod.apply(this, args);};};
}class DocumentService {@PermissionRequired("WRITE")editDocument() {console.log("Document is being edited.");}
}const documentService = new DocumentService();
documentService.editDocument(); // 如果权限包含 "WRITE",则输出 "Document is being edited."
解释:@PermissionRequired
装饰器会在方法执行前检查当前用户的权限。如果权限不足,则拒绝执行方法。
组合使用装饰器
在实际项目中,装饰器可以进行组合使用,进行多种功能的扩展。例如,我们可以结合使用日志记录和权限校验装饰器:
function Log(target: any, propertyName: string, descriptor: PropertyDescriptor) {const originalMethod = descriptor.value;descriptor.value = function (...args: any[]) {console.log(`Calling method ${propertyName} with arguments: ${args}`);return originalMethod.apply(this, args);};
}function PermissionRequired(permission: string) {return function (target: any, propertyName: string, descriptor: PropertyDescriptor) {const originalMethod = descriptor.value;descriptor.value = function (...args: any[]) {const userPermissions = ["READ", "WRITE"];if (!userPermissions.includes(permission)) {console.log(`Permission denied. Missing permission: ${permission}`);return;}return originalMethod.apply(this, args);};};
}class FileService {@Log@PermissionRequired("READ")readFile(filePath: string) {console.log(`Reading file from ${filePath}`);}
}const fileService = new FileService();
fileService.readFile("/path/to/file");
解释:此时,readFile
方法同时拥有日志记录和权限校验的功能,先打印调用日志,再检查权限。
总结
TypeScript 装饰器是一种强大的工具,可以在类、方法、属性、参数等地方进行功能扩展,常用于日志记录、权限校验、性能监控等场景。在实际开发中,装饰器的应用通常能大大减少冗余代码、提高代码的可维护性和灵活性。通过装饰器,开发者可以以声明式的方式对类和方法进行增强,并实现高层次的抽象和代码重用。
常见应用场景:
- 日志记录
- 性能监控
- 权限校验
- 依赖注入
- 数据验证
- 缓存机制
理解装饰器及其应用方式,可以让你在开发中更加得心应手,特别是当代码规模增大时,装饰器能够帮助你以更简洁的方式处理复杂的逻辑。
相关文章:
TypeScript 装饰器都有那些应用场景?如何更快的上手?
TypeScript 装饰器简介 在 TypeScript 中,装饰器(Decorators)是一种特殊的语法,用于在类、类方法、属性、访问器等上动态地添加行为或修改现有行为。装饰器可以用来增强类的功能、修改方法的行为,或者修改类的元数据等…...
堆优化版本的Prim
prim和dijkstra每轮找最小边的松弛操作其实是同源的,因而受dijkstra堆优化的启发,那么prim也可以采用小根堆进行优化。时间复杂度也由 O ( n 2 ) O(n^2) O(n2)降为 O ( n l o g n ) O(nlogn) O(nlogn)。 测试一下吧:原题链接 #include <i…...

Ubuntu上安装MySQL并且实现远程登录
目录 下载网络工具 查看网络连接 更新系统软件包; 安装mysql数据库 查看mysql数据库状态 以数字ip形式显示mysql的监听状态。(默认监听端口是3306) 查看安装mysql数据库时系统创建的目录信息。 根据查询到的系统用户名以及随机密码&a…...

蓝桥杯每日真题 - 第21天
题目:(空间) 题目描述(12届 C&C B组A题) 解题思路: 转换单位: 内存总大小为 256MB,换算为字节: 25610241024268,435,456字节 计算每个整数占用空间: 每个 32 位整数占用…...

(长期更新)《零基础入门 ArcGIS(ArcMap) 》实验一(下)----空间数据的编辑与处理(超超超详细!!!)
续上篇博客(长期更新)《零基础入门 ArcGIS(ArcMap) 》实验一(上)----空间数据的编辑与处理(超超超详细!!!)-CSDN博客 继续更新 目录 什么是拓扑? 1.3.5道路…...

NLP论文速读(CVPR 2024)|使用DPO进行diffusion模型对齐
论文速读|Diffusion Model Alignment Using Direct Preference Optimization 论文信息: 简介: 本文探讨的背景是大型语言模型(LLMs)通过人类比较数据和从人类反馈中学习(RLHF)的方法进行微调,以…...

操作系统——揭开盖子
计算机执行时——取指执行 es:bx等于从0x9000开始,到0x90200结束...
如何在 React 项目中应用 TypeScript?应该注意那些点?结合实际项目示例及代码进行讲解!
在 React 项目中应用 TypeScript 是提升开发效率、增强代码可维护性和可读性的好方法。TypeScript 提供了静态类型检查、自动补全和代码提示等功能,这对于 React 开发者来说,能够帮助早期发现潜在的 bug,提高开发体验。 1. 项目初始化 在现…...

C++学习第四天
创作过程中难免有不足,若您发现本文内容有误,恳请不吝赐教。 提示:以下是本篇文章正文内容,下面案例可供参考 一、计算类对象的大小 #include<iostream> using namespace std;class Date { public:void Init(int year, in…...

【从零开始的LeetCode-算法】3232. 判断是否可以赢得数字游戏
给你一个 正整数 数组 nums。 Alice 和 Bob 正在玩游戏。在游戏中,Alice 可以从 nums 中选择所有个位数 或 所有两位数,剩余的数字归 Bob 所有。如果 Alice 所选数字之和 严格大于 Bob 的数字之和,则 Alice 获胜。 如果 Alice 能赢得这场游…...
一种简单高效的RTSP流在线检测方法,不需要再过渡拉流就可以获取设备状态以及对应音视频通道与编码格式
平台如何检测一路RTSP流是否在线? 在之前的流媒体平台方案中,我们都是通过定时RTSP拉流的方式,走一个完整的RTSP流程:包括OPTIONS、DESCRIBE、SETUP、PLAY、RTP收流,这种方式去取流,然后取到流之后进行流解…...

24/11/22 项目拆解 艺术风格转移
我们有时候想把两种艺术风格整合,创造更具艺术特色的艺术品,人很难办到,但是人工智能可以,比如下面将艺术画的风格转移到照片上。 我们先来初步了解一下实现上述功能的数学原理 所谓艺术风格,其实就是边缘,颜色&#…...

数字赋能,气象引领 | 气象景观数字化服务平台重塑京城旅游生态
在数字化转型的浪潮中,旅游行业正以前所未有的速度重塑自身,人民群众对于高品质、个性化旅游服务需求的日益增长,迎着新时代的挑战与机遇,为开展北京地区特色气象景观预报,打造“生态气象旅游”新业态,助推…...

关于Redux的学习(包括Redux-toolkit中间件)
目录 什么是 Redux ? 我为什么要用 Redux ? 我什么时候应该用 Redux ? Redux 库和工具 React-Redux Redux Toolkit Redux DevTools 拓展 一个redux小示例 代码示例(很有用): Redux 术语 Actions Reducers Store Dis…...
【无人机】
GJI Mini 4 Pro学习 首次飞行使用 01 开箱 打开长飞套装 依次取出产品及配件 飞行器、DJI RC - N2(DJI RC 2)、桨叶/螺丝、云台保护罩、束桨器、电池、螺丝刀、USB-C快接线、单肩包、USB-C数据线、充电管家 02 准备飞行器 取下束桨器,…...

Zabbix7.0.6的容器镜像准备
准备Zabbix7.0.6部署所需的容器镜像。 更新时间:20241122 一、准备数据库镜像 1、核对版本支持 根据Zabbix官网文档requirements 可知,当前最新的Zabbix 7.0.6对PostgreSQL数据库的要求如下: support for PostgreSQL versions:- 17.X …...

利用 GitHub 和 Hexo 搭建个人博客【保姆教程】
利用 GitHub 和 Hexo 搭建个人博客 利用 GitHub 和 Hexo 搭建个人博客一、前言二、准备工作(一)安装 Node.js 和 Git(二)注册 GitHub 账号 三、安装 Hexo(一)创建博客目录(二)安装 H…...
React第四节 组件的三大属性之state
前言 状态 state适用于类式组件中,而再函数式组件中需要使用 useState HOOK 模拟状态; React的组件就是一个状态机,通过与用户的交互,实现不同的状态,根据不同的状态展现出不一样的UI视图 并不是组件中所有的属性 都是组件的状态…...

MongoDB进阶篇-索引(索引概述、索引的类型、索引相关操作、索引的使用)
文章目录 1. 索引概述2. 索引的类型2.1 单字段索引2.2 复合索引2.3 其他索引2.3.1 地理空间索引(Geospatial Index)2.3.2 文本索引(Text Indexes)2.3.3 哈希索引(Hashed Indexes) 3. 索引相关操作3.1 查看索…...

使用FFmpeg实现视频与GIF的画中画效果
用FFmpeg命令行工具将GIF动画作为画中画(Picture-in-Picture,简称PiP)叠加到视频上。FFmpeg是一个强大的多媒体框架,能够处理几乎所有格式的音频和视频文件。通过这个教程,你将学会如何将一个小的GIF动画循环播放&…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...

地震勘探——干扰波识别、井中地震时距曲线特点
目录 干扰波识别反射波地震勘探的干扰波 井中地震时距曲线特点 干扰波识别 有效波:可以用来解决所提出的地质任务的波;干扰波:所有妨碍辨认、追踪有效波的其他波。 地震勘探中,有效波和干扰波是相对的。例如,在反射波…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...

面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...

mac 安装homebrew (nvm 及git)
mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用: 方法一:使用 Homebrew 安装 Git(推荐) 步骤如下:打开终端(Terminal.app) 1.安装 Homebrew…...

PH热榜 | 2025-06-08
1. Thiings 标语:一套超过1900个免费AI生成的3D图标集合 介绍:Thiings是一个不断扩展的免费AI生成3D图标库,目前已有超过1900个图标。你可以按照主题浏览,生成自己的图标,或者下载整个图标集。所有图标都可以在个人或…...