Using a class definition

Before we begin, bear in mind that in order to use decorators, our tsconfig.json file must be configured correctly, as follows:

{ 
    "compilerOptions": { 
        "target": "es6", 
        "module": "commonjs", 
        "lib": [ 
            "es6" 
        ], 
        "strict": true,  
        "esModuleInterop": true, 
        "experimentalDecorators": true, 
        "emitDecoratorMetadata": true,  
    } 
} 

Here, we have included the "experimentalDecorators" : true option, as well as the "emitDecoratorMetadata" : true option in order for our code to use decorators, as we did in Chapter 4, Decorators, Generics and Asynchronous Features. We have also defined that we wish to use ES6 as our compile target, and have included the es6 library in our lib definition. We will also need to install the reflect-metadata package, as follows:

npm install reflect-metadata 

Let's put together a simple class decorator, and see what information we can deduce from the class. Our decorator, in the Decorator.ts file is as follows:

import 'reflect-metadata'; 
export function ConstructorInject(classDefinition: Function) { 
    console.log(`classDefinition:`); 
    console.log(`================`); 
    console.log(`${classDefinition}`); 
    console.log(`================`); 
} 

Here, we are importing the reflect-metadata module, and have then created a decorator that is simply logging the value of the classDefinition argument to the console.

We can now decorate our MailServiceDi class with this decorator, and see what happens:

import { ConstructorInject } from './ConstructorInject'; 
 
@ConstructorInject 
export default class MailServiceDi { 
    private _transporter: nodemailer.Transporter; 
    private _settings: ISystemSettings; 
     
    constructor(_settings?: IISystemSettings) { 
    } 
} 

Here, we have imported our ConstructorInject decorator, and applied it to our MailServiceDi class. Note that for the sake of brevity, we have removed the body of the constructor code that configures the _transporter property. If we now create an instance of this class, it will be as follows:

import MailServiceDi from './MailServiceDi'; 
var gmailDi = new MailServiceDi(); 

We will generate the following console output from our ConstructorInject decorator, as follows:

classDefinition:
================
class MailServiceDi {
    constructor(_settings) {
    }
}
================  

As we can see, the classDefinition parameter is populated with the full class definition for the MailServiceDi class. This definition, however, is not the TypeScript definition of our class, but it is the JavaScript definition of our class. This means that we have lost the type information on each of our constructor parameters, as this information is compiled away. What we do have, however, is the name of the properties that this class uses in its constructor.

The generated JavaScript will always include the constructor as the first function. If we were to add any other function at the top of the class definition, and write the constructor at the bottom of the class definition, TypeScript will always move the constructor function to the top of the class definition.
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.224.0.25