Preface: 1. Concept 1.1 Definition A decorator is a new type of declaration that can be applied to class declarations, methods, accessors, properties, and parameters. The decorator is used with the @ symbol plus a function name, such as It is worth noting that the decorator should be placed immediately before the content to be modified, and all decorators cannot be used in declaration files.d.ts. and any external context (such as The definition and use of the decorator are as follows: // Define a function as a decorator function to use function testDecorator() {} //Use the decorator @testDecorator via the @ symbol 1.2 Decorator FactoryThe so-called decorator factory is also a function. The difference from the ordinary decorator function is that its return value is a function, and the returned function is used as the function called by the decorator. If you use a decorator factory, you can pass different parameters according to the current usage when using it, but when using it, you need to add a function call. The sample code is as follows: // Decorator factory, the return value is a function function testDecorator() { return function() {} } //Use the decorator @testDecorator() by @symbol + function call 1.3 Decorator CombinationDecorators can be used in combination, that is, you can use one target and reference multiple decorators. The sample code is as follows: // Define two decorator functions function setName() {} function setAge() {} //Use decorator @setName @setAge class Person {} If multiple decorators are used, the decorators are executed in order, and the execution order is as follows: If a normal decorator function is used, the execution order is from bottom to top. The sample code is as follows: function setName(constructor: any) { console.log('setName', constructor) } function setAge(constructor: any) { console.log('setAge', constructor) } @setName @setAge class Person {} /* The execution results are as follows: setAge [Function: Person] setName [Function: Person] */ If it is a decorator factory, its execution order is to execute the factory function from top to bottom, and then execute the function returned by the factory function from bottom to top. The sample code is as follows function setName() { console.log('get setName') return function (constructor: any) { console.log('setName', constructor) } } function setAge() { console.log('get setAge') return function (constructor: any) { console.log('setAge', constructor) } } @setName() @setAge() class Person {} /* The execution results are as follows: get setName get setAge setAge [Function: Person] setName [Function: Person] */ 1.4 Decorator EvaluationDecorators on different declarations in a class definition are applied in the order specified below:
2. Class DecoratorClass decorators are used before class declarations and must be placed immediately before the content to be decorated. Class decorators are applied to class declarations. The class decorator expression will be called as a function at runtime, and it has one parameter, which is the constructor of this class. The sample code is as follows: let sign = null function setName() { return function (constructor: Function) { sign = constructor } } @setName() class Info { constructor() {} } console.log(sign === Info) // true console.log(sign === Info.prototype.constructor) // true From the above code, we can see that We can also use decorators to modify the prototype object and constructor of a class. The sample code is as follows: // * Modify the prototype object and constructor function addName(constructor: { new (): any }) { constructor.prototype.name = 'A bowl of Zhou' } @addName class Person {} const person = new Person() console.log(person.name) // error Property "name" does not exist on type "A" In the above code, we use the The sample code is as follows: function addName(constructor: { new (): any }) { constructor.prototype.name = 'A bowl of Zhou' } @addName class Person {} const person = new Person() // 1. Type assertion // console.log((person as any).name) // 一碗周 // 2. Define an interface with the same name and declare a merge interface Person { name: string } console.log(person.name) // Yiwan Zhou And we can also overload the constructor through the decorator, the sample code is as follows: // * Overload the constructor function classDecorator<T extends { new (...args: any[]): {} }>( constructor: T, ) { return class extends constructor { name = 'A bowl of Zhou' hobby = 'coding' } } @classDecorator class Person { age = 18 name: string constructor(name: string) { this.name = name } } const person = new Person('Yiwan Zhou') console.log(person) /* The execution results are as follows: { age: 18, name: 'A bowl of Zhou', hobby: 'coding', } */ We can also pass parameters through the decorator factory. The sample code is as follows: // Define a decorator factory function classDecorator(_name: string) { return function <T extends { new (...args: any[]): {} }>(constructor: T) { return class extends constructor { name = _name hobby = 'coding' } } } @classDecorator('A bowl of Zhou') class Person { age = 18 name: string constructor(name: string) { this.name = name } } const person = new Person('a bowl of porridge') console.log(person) /* The execution results are as follows: { age: 18, name: 'A bowl of Zhou', hobby: 'coding', } */ 3. Method DecoratorThe method decorator is used to process the methods in the class. It can process the property descriptor of the method (for what is the property descriptor, please refer to Object.defineProperty()) and the method definition. The method decorator is also called as a function at runtime, which contains three parameters. The details are as follows: For static members, it is the class constructor; for instance members, it is the class prototype object. The member's first name. The property descriptor of the member. Note that if the code output targets a version less than ES5, the property descriptor will be The following code defines a simple method decorator through the decorator factory. The sample code is as follows: // Decorator factory function enumerable(bool: boolean) { /** * The method decorator accepts three parameters: * 1. target: for static members, it is the constructor of the class; for instance members, it is the prototype object of the class* 2. propertyName: the name of the member* 3. descriptor: property descriptor, its type is PropertyDescriptor */ return function ( target: any, propertyName: string, descriptor: PropertyDescriptor, ) { //Determine whether the method is enumerable based on the passed bool descriptor.enumerable = bool } } class Info { constructor(public name: string) {} @enumerable(false) getName() { return this.name } } const info = new Info('A bowl of Zhou') // If printed directly, the object does not contain the getName() method because the method is not enumerable. console.log(info) // { name: 'Yiwan Zhou' } // But you can call this method console.log(info.getName()) // Yiwan Zhou In the above code, we directly modified the property descriptor of the method in the class through the decorator. If the method decorator returns a value, then this value will be used as the property descriptor object of the method. The sample code is as follows: // Decorator factory function enumerable(bool: boolean) { return function ( target: any, propertyName: string, descriptor: PropertyDescriptor, ) { return { value: function () { return 'Error: name is undefined' }, enumerable: bool, } } } class Info { constructor(public name: string) {} @enumerable(false) getName() { return this.name } } const info = new Info('A bowl of Zhou') console.log(info) // { name: 'Yiwan Zhou' } console.log(info.getName()) // Error: name is undefined In the above code, our method decorator returns an object whose value property modifies the method definition, so the final result is 4. Accessor Decorator The accessor decorator is The accessor decorator also accepts three parameters, just like the method decorator, so I won’t go into details here. The sample code is as follows: function enumerable(bool: boolean) { return function ( target: any, propertyName: string, descriptor: PropertyDescriptor, ) { descriptor.enumerable = bool } } class Info { private_name: string constructor(name: string) { this._name = name } @enumerable(false) get name() { return this._name } set name(name) { this._name = name } } It is worth noting that in 5. Property DecoratorThe property decorator is declared before the property declaration and it has two parameters as shown below:
The sample code is as follows: function printPropertyName(target: any, propertyName: string) { console.log(propertyName) } class Info { @printPropertyName name: string @printPropertyName age: number constructor(name: string, age: number) { this.name = name this.age = age } } new Info('Yiwan Zhou', 18) The execution results are as follows:
6. Parameter DecoratorThe parameter decorator has three parameters, as follows:
The function of the parameter decorator is to monitor whether a method parameter is passed in. The return value of the parameter decorator will be ignored. The sample code is as follows: function required(target: any, propertyName: string, index: number) { console.log(`The modified parameter is the ${index + 1}th parameter of ${propertyName}`) } class Info { name: string = 'A bowl of Zhou' age: number = 18 getInfo(prefix: string, @required infoType: string): any { return prefix + ' ' + this[infoType] } } interface Info { [key: string]: string | number | Function } const info = new Info() info.getInfo('', 'age') // Modifies the second parameter of getInfo Here we use the parameter decorator before the second parameter of This is the end of this article about TypeScript decorator definitions. For more information about TypeScript decorators, please search 123WORDPRESS.COM’s previous articles or continue to browse the following related articles. I hope you will support 123WORDPRESS.COM in the future! You may also be interested in:
|
<<: MySQL time types and modes details
>>: Implementation of CSS equal division of parent container (perfect thirds)
Now there are many WeChat public account operatio...
When I created a Docker container today, I accide...
First put a piece of code for(int i=0;i<1000;i...
Sometimes, we want the text boxes in the form to b...
Table of contents Preface Introduction ngram full...
1. Introduction First of all, we need to answer a...
Effect If you use it, please optimize the code an...
Sttty is a common command for changing and printi...
As the company's influence grows and its prod...
This article shares the specific code of the firs...
Recently, when doing homework, I needed to nest a ...
CSS display property Note: If !DOCTYPE is specifi...
A colleague asked me what N and M mean in the MyS...
Vim is a powerful full-screen text editor and the...
<br />Forms are an important channel for use...