- TypeScript 基础
- TypeScript - 首页
- TypeScript - 路线图
- TypeScript - 概述
- TypeScript - 环境搭建
- TypeScript - 基本语法
- TypeScript vs. JavaScript
- TypeScript - 特性
- TypeScript - 变量
- TypeScript - let & const
- TypeScript - 运算符
- TypeScript 基本类型
- TypeScript - 类型
- TypeScript - 类型注解
- TypeScript - 类型推断
- TypeScript - 数字
- TypeScript - 字符串
- TypeScript - 布尔值
- TypeScript - 数组
- TypeScript - 元组
- TypeScript - 枚举
- TypeScript - Any
- TypeScript - Never
- TypeScript - 联合类型
- TypeScript - 字面量类型
- TypeScript - 符号
- TypeScript - null vs. undefined
- TypeScript - 类型别名
- TypeScript 控制流
- TypeScript - 决策语句
- TypeScript - If 语句
- TypeScript - If Else 语句
- TypeScript - 嵌套 If 语句
- TypeScript - Switch 语句
- TypeScript - 循环
- TypeScript - For 循环
- TypeScript - While 循环
- TypeScript - Do While 循环
- TypeScript 函数
- TypeScript - 函数
- TypeScript - 函数类型
- TypeScript - 可选参数
- TypeScript - 默认参数
- TypeScript - 匿名函数
- TypeScript - 函数构造器
- TypeScript - Rest 参数
- TypeScript - 参数解构
- TypeScript - 箭头函数
- TypeScript 接口
- TypeScript - 接口
- TypeScript - 扩展接口
- TypeScript 类和对象
- TypeScript - 类
- TypeScript - 对象
- TypeScript - 访问修饰符
- TypeScript - 只读属性
- TypeScript - 继承
- TypeScript - 静态方法和属性
- TypeScript - 抽象类
- TypeScript - 访问器
- TypeScript - 鸭子类型
- TypeScript 高级类型
- TypeScript - 交叉类型
- TypeScript - 类型守卫
- TypeScript - 类型断言
- TypeScript 类型操作
- TypeScript - 从类型创建类型
- TypeScript - Keyof 类型操作符
- TypeScript - Typeof 类型操作符
- TypeScript - 索引访问类型
- TypeScript - 条件类型
- TypeScript - 映射类型
- TypeScript - 模板字面量类型
- TypeScript 泛型
- TypeScript - 泛型
- TypeScript - 泛型约束
- TypeScript - 泛型接口
- TypeScript - 泛型类
- TypeScript 杂项
- TypeScript - 三斜杠指令
- TypeScript - 命名空间
- TypeScript - 模块
- TypeScript - 环境声明
- TypeScript - 装饰器
- TypeScript - 类型兼容性
- TypeScript - Date 对象
- TypeScript - 迭代器和生成器
- TypeScript - Mixins
- TypeScript - 实用程序类型
- TypeScript - 装箱和拆箱
- TypeScript - tsconfig.json
- 从 JavaScript 到 TypeScript
- TypeScript 有用资源
- TypeScript - 快速指南
- TypeScript - 有用资源
- TypeScript - 讨论
TypeScript - 装饰器
TypeScript 中的装饰器是一种特殊的声明,可以附加到类声明、属性、访问器、方法和参数上。它用于在不修改原始源代码的情况下单独修改类。这使得它们成为面向对象编程领域中强大的工具,允许您编写更简洁、更有条理的代码,并遵循 DRY(不要重复自己)原则。
在 TypeScript 中使用装饰器
您需要启用“experimentalDecorators”编译器选项以启用 TypeScript 项目中对装饰器的实验性支持。
有两种方法可以在 TypeScript 中启用“experimentalDecorators”编译器选项。您可以使用任何一个选项。
- 在项目目录的终端中执行以下命令。tsc --target ES5 --experimentalDecorators
- 或者,您可以更新tsconfig.js文件并在 compilerOptions 对象中添加"experimentalDecorators": true 属性。
{ "compilerOptions": { "target": "ES5", "experimentalDecorators": true } }
装饰器语法
您可以按照以下语法在 TypeScript 中使用装饰器。
@DecoratorName
在上述语法中,“DecoratorName”是带有“@”符号前缀的函数名。表达式必须在运行时计算“DecorateName”函数。
装饰器工厂
每当您需要自定义装饰器函数如何应用于声明时,它们可以使用装饰器工厂。装饰器工厂函数返回将在运行时计算的表达式。
请按照以下语法使用装饰器工厂函数。
function decoratorName(args: string) { // Decorator factory returns the function expression return function (target) { // This is the decorator which will be evaluated at the run time. }; }
在上述语法中,“args”是传递给装饰器函数的参数,“target”是类的原型。
装饰器组合
您可以将多个装饰器与特定声明一起使用。多个装饰器可以单行使用或多行使用,如下所示。
单行
@f @g x
或者,多行
@f @g x
在上述语法中,“f”和“g”装饰器与单个声明“x”一起使用。
为什么要使用装饰器?
让我们举一个简单的例子来了解装饰器的用例。
// Defining a class class Student { // Declaring the properties of the class constructor(private name: string, private rollNo: number) { } // Defining the methods of the class sayHello() { console.log(`Hello, my name is ${this.name}.`); } printrollNo() { console.log(`My RollNo is ${this.rollNo}.`); } } // Creating an object of the class const user = new Student("John", 20); // Accessing the properties of the class user.sayHello(); user.printrollNo();
编译后,它将生成以下 JavaScript 代码
// Defining a class class Student { // Declaring the properties of the class constructor(name, rollNo) { this.name = name; this.rollNo = rollNo; } // Defining the methods of the class sayHello() { console.log(`Hello, my name is ${this.name}.`); } printrollNo() { console.log(`My RollNo is ${this.rollNo}.`); } } // Creating an object of the class const user = new Student("John", 20); // Accessing the properties of the class user.sayHello(); user.printrollNo();
它产生以下输出
Hello, my name is John. My RollNo is 20.
现在,如果我们希望在函数执行开始和结束时记录该函数,该怎么办?我们需要在每个函数的开头和结尾添加日志,如下面的代码所示。
// Defining a class class Student { // Declaring the properties of the class constructor(private name: string, private rollNo: number) { } // Defining the methods of the class sayHello() { console.log("Start: sayHello"); console.log(`Hello, my name is ${this.name}.`); console.log("End: sayHello"); } printrollNo() { console.log("Start: printrollNo"); console.log(`My RollNo is ${this.rollNo}.`); console.log("End: printrollNo"); } } // Creating an object of the class const user = new Student("John", 20); // Accessing the properties of the class user.sayHello(); user.printrollNo();
编译后,它将生成以下 JavaScript 代码
// Defining a class class Student { // Declaring the properties of the class constructor(name, rollNo) { this.name = name; this.rollNo = rollNo; } // Defining the methods of the class sayHello() { console.log("Start: sayHello"); console.log(`Hello, my name is ${this.name}.`); console.log("End: sayHello"); } printrollNo() { console.log("Start: printrollNo"); console.log(`My RollNo is ${this.rollNo}.`); console.log("End: printrollNo"); } } // Creating an object of the class const user = new Student("John", 20); // Accessing the properties of the class user.sayHello(); user.printrollNo();
它将产生以下输出
Start: sayHello Hello, my name is John. End: sayHello Start: printrollNo My RollNo is 20. End: printrollNo
如果我们想重用记录函数执行的逻辑而不编写重复的代码,该怎么办?在这里,装饰器就派上用场了。
让我们通过下面的例子来学习它。
// Decorator factory function printExecution(method: any, _context: any) { // Returning a new function return function (value: any, ...args: any[]) { // Logging the method name at the start console.log("start:", method.name); // Calling the original method const result = method.call(value, ...args); // Logging the method name at the end console.log("end:", method.name); return result; } } // Defining a class class Student { // Declaring the properties of the class constructor(private name: string, private rollNo: number) { } // Defining the methods of the class @printExecution sayHello() { console.log(`Hello, my name is ${this.name}.`); } @printExecution printrollNo() { console.log(`My RollNo is ${this.rollNo}.`); } } // Creating an object of the class const user = new Student("John", 20); // Accessing the properties of the class user.sayHello(); user.printrollNo();
以上代码打印与之前代码相同的输出。
Start: sayHello Hello, my name is John. End: sayHello Start: printrollNo My RollNo is 20. End: printrollNo
类装饰器
类装饰器与类声明一起使用,以观察或修改类定义。
示例
// Decorator factory function LogClass(target: Function) { console.log(`${target.name} is instantiated`); } // Decorator @LogClass class MyClass { constructor() { console.log("MyClass instance created"); } } // Create an instance of the class const myClassInstance = new MyClass();
编译后,它将生成以下 JavaScript 代码
// Class definition class MyClass { constructor() { console.log("MyClass instance created"); } } // Decorator LogClass(MyClass); // Create an instance of the class const myClassInstance = new MyClass();
输出
MyClass instance created MyClass is instantiated
方法装饰器
方法装饰器用于替换、修改或观察方法定义。它与方法定义一起使用。
示例
// Decorator factory function printExecution(method: any, _context: any) { // Returning a new function return function (value: any, ...args: any[]) { // Logging the method name at the start console.log("start:", method.name); // Calling the original method const result = method.call(value, ...args); return result; } } // Defining a class class Person { constructor(private name: string) { } // Decorator @printExecution printName() { console.log(`Hello, my name is ${this.name}.`); } } // Create an object of the class const user = new Person("John"); // Accessing the properties of the class user.printName();
输出
start: printName Hello, my name is John.
访问器装饰器
访问器装饰器与 get() 和 set() 访问器一起使用,以观察、替换和修改访问器的定义。
示例
// Decorator factory function LogAccessor(method: any) { console.log("Getter called"); } // Define a class class MyClass { private _name: string = "MyClass"; // Decorator @LogAccessor get name() { return this._name; } } const instance = new MyClass(); console.log(instance.name);
输出
Getter called MyClass
属性装饰器
属性装饰器与属性一起使用,以修改、替换和观察它。
示例
// Decorator function to log the property name function LogProperty(target: any, propertyKey: string) { console.log(`Property declared: ${propertyKey}`); } class Person { // Decorator is applied to the property @LogProperty name: string; @LogProperty age: number; constructor(name: string, age: number) { this.name = name; this.age = age; } } let person = new Person('Jay', 23);
输出
Property declared: name Property declared: age
参数装饰器
参数装饰器与方法参数一起使用,以观察、修改和替换它们。
示例
// Decorator with parameter function LogParameter(target: any, methodName: string, parameterIndex: number) { console.log(`Parameter in ${methodName} at index ${parameterIndex} has been decorated`); } // Class decorator class MyClass { myMethod(@LogParameter param: string) { console.log(`Executing myMethod with param: ${param}`); } } // Create an instance of the class const instance = new MyClass(); instance.myMethod("test");
输出
Parameter in myMethod at index 0 has been decorated Executing myMethod with param: test
我们已经学习了如何在 TypeScript 中创建自定义装饰器。但是,用户可以将预定义的装饰器用于各种目的,例如调试代码等。