typescript 模块
If you have worked with a framework like Angular you have used syntax such as @Component
, @HostListenerand
and @viewchild
. These are known as TypeScript decorators. They are one of the most powerful yet under-used features of TypeScript.
如果您使用过类似Angular的框架,则可以使用诸如@Component
@HostListenerand
, @Component
@HostListenerand
和@viewchild
@Component
语法。 这些被称为TypeScript装饰器。 它们是TypeScript最强大但未充分使用的功能之一。
In this article we will discuss:
在本文中,我们将讨论:
- What decorators are 什么是装饰
- How to implement your own decorators 如何实现自己的装饰器
- Leveraging decorators to write clean modular code 利用装饰器编写干净的模块化代码
- Aspect Oriented Programming and decorators 面向方面的编程和装饰器
- Cross-cutting-concerns and solving them with decorators 横切问题,并用装饰器解决
首先-什么是装饰器? (First - What is a Decorator?)
A decorator is a function that allows us to annotate our code or hook into its behavior (similar to meta-programming).
装饰器是允许我们注释代码或挂钩其行为的函数(类似于元编程)。
Decorators are very good at creating abstractions. When a piece of logic needs to be duplicated in many places we can use a decorator for it. Decorators also solve problems that are hard to solve with inheritance (more on this later).
装饰者非常擅长创建抽象。 当需要在许多地方复制逻辑时,可以使用装饰器。 装饰器还解决了难以通过继承解决的问题(稍后会详细介绍)。
There are 4 types of Decorators in TypeScript and they are as follows:
TypeScript中有4种类型的Decorator,它们如下:
类装饰器 (Class Decorators)
A Class Decorator is declared before a class declaration. A class decorator is applied to the constructor of the class and can be used to observe, modify, or replace a class definition.
在类声明之前声明类装饰器。 类装饰器应用于类的构造函数,可用于观察,修改或替换类定义。
Here’s an example:
这是一个例子:
@robot
class Greeter {
private greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
}
function robot<T extends { new (...args: any[]): {} }>(constructor: T) {
return class extends constructor {
greeting = "from Robot :-{";
};
}
let k = new Greeter("shadid");
console.log(k.greet());
In this example we are overriding the constructor of our Greeter
class. Our robot
decorator function is just like a normal function. However, it takes in a class constructor as an argument. We can use this constructor that is being passed in as a parameter and override its functionality.
在此示例中,我们将重写Greeter
类的构造函数。 我们的robot
装饰器功能就像普通功能一样。 但是,它将类构造函数作为参数。 我们可以使用此构造函数作为参数传入,并覆盖其功能。
方法装饰器 (Method Decorator)
A Method Decorator is declared before a method declaration. It is applied to the Property Descriptor for the method, and can be used to observe, modify, or replace a method definition.
在方法声明之前声明方法装饰器。 它应用于方法的属性描述符,并且可以用于观察,修改或替换方法定义。
Here’s an example:
这是一个例子:
declare type MethodDecorator = <T>(
target: Object,
propertyKey: string | symbol,
descriptor: TypedPropertyDescriptor<T>
) => TypedPropertyDescriptor<T> | void;
class Robot {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
@logMethod("Greet")
greet() {
return "Hello, " + this.greeting;
}
}
function logMethod(message: string): MethodDecorator {
console.log(`${message} evaluated`);
return function(
target: Object,
propertyKey: string,
descriptor: PropertyDescriptor
): void {
console.log(`${message} called`);
};
}
let bot = new Robot("I am robo, nice to meet you :)");
console.log(bot.greet());
Here we first defined a MethodDecorator
type. We created a method decorator called logMethod
. This decorator function is a factory function that returns another function of type MethodDecorator. While using decorators it is a common practice to use a factory function. The returned function is where we will usually apply our logic.
在这里,我们首先定义了MethodDecorator
类型。 我们创建了一个名为logMethod
的方法装饰器。 此装饰器函数是一个工厂函数,它返回另一个类型为MethodDecorator的函数。 使用装饰器时,通常使用工厂功能。 返回的函数通常是我们应用逻辑的地方。
物业装饰 (Property Decorator)
The Property Decorator is applied to a Property definition. You are probably noticing a pattern already 😊. Below is an example:
属性装饰器应用于属性定义。 您可能已经注意到一种模式😊。 下面是一个示例:
class Greeter {
@logGreet("Logging Greetings")
greeting: string;
....
}
function logGreet(formatString: string) {
console.log(formatString);
}
参数装饰器 (Parameter Decorator)
As the name suggests, this decorator is applied to the parameters of methods. Below is an example:
顾名思义,此装饰器应用于方法的参数。 下面是一个示例:
class Greeter {
...
public makeRobotNoise(
@logParameter("Param for method robot noise") person: Person
) {
this._directReports.push(person);
}
}
function logParameter(message: string): ParameterDecorator {
console.log(`${message} logParam factory`);
return function(
target: Object,
propertyKey: string,
parameterIndex: number
): void {
console.log(`${message} called from return function`);
};
}
These are some of the basic examples of decorators. Now let's work though a real world project together where we can implement decorators to cut down repeated functionality in our code.
这些是装饰器的一些基本示例。 现在,让我们一起完成一个真实的项目,在这里我们可以实现装饰器,以减少代码中的重复功能。
应用我们所学 (Applying what we've learned)
如何实现自己的装饰器 (How to implement your own decorators)
We will be building a REST api server with Node.js, Express and TypeScript. We will structure our code for scalability and proper testing. We will also look at a concept called Aspect Oriented Programming (AOS) and apply a layered architecture.
我们将使用Node.js,Express和TypeScript构建REST api服务器。 我们将为可伸缩性和适当的测试构造代码。 我们还将研究称为面向方面编程(Aspect Oriented Programming,AOS)的概念,并应用分层体系结构。
Alright let's dive in.
好吧,让我们潜入。
Get the starter code from the following directory. I have setup a TypeScript project with Express for you to follow along.
从以下目录获取入门代码。 我已经使用Express设置了TypeScript项目,以供您遵循。
https://github.com/Shadid12/entity-framework/tree/intro_1
https://github.com/Shadid12/entity-framework/tree/intro_1
Let's go over the project together.
让我们一起来看一下这个项目。
src/app.ts
src/app.ts
import APIServer from "./APIServer";
export const apiServer = new APIServer();
apiServer.start();
app.ts
is our application entry point. You can see that we are creating an instance of the APIServer
class and calling the start()
method. APISe