Here are the sections for current article:
- What is Decorator
- Types of Decorator
- Creating the function with our custom made function decorator
1. What is Decorator?
Decorators provide a way to add both annotations and a meta-programming syntax for class declarations and members. And these decorators wrap the context and gives you a way to process the context, add something extra in the context and even change the context. The word context means, that in case of a function decorator you can have the access to the Class to which the function belongs, the passed parameters of the actual function call and many more.
2. Types of Decorators?
We have many different type of decorators. Some of them are:
- Class Decorators
- Function Decorators
- Property Decorator
- Accessor Decorator
And we have some others too but the above ones are most useful as well as popular. For further details on the above mentioned types please have a look at TypeScript Decorators.
In a nutshell, decorators are special kind of functions that return another special kind of functions which is called as a wrapped up contextual function to the actual context on which the decorator function is applied.
Sounds a bit over complex but is pretty simple to understand. Lets look at the below code:
If you check out the function first & second are the decorator factories who are returning a special function and this returned function is called as a contextual wrapped function for the specific context on which first and second is applied, so in our case the console will look like:
So, if we see the logs, we get the understanding that the factories are called and the actual function (returns of factories) of these factories gets attached to the contextual block which in our case is a method of ExampleClass.
Now lets prepare a basic log based function decorator which will log the arguments before entering the function call as well as after completing the function execution. Here is main code of the LogMe decorator and we will then see the executional part.
For now just concentrate on line 18, 33, and 57.
Line 18: The function that will be called before the actual contextual block on which LogMe is applied
Line 33: The function that will be called after the actual contextual block on which LogMe is applied
Line 57: This is a utility function from nestjs that clubs all the decorator factories and lets you apply all of them with 1 clubbed name in our case its LogMe.
Line 11: is basically a DTO of passing the arguments for the behavior of out Logger, like whether to log anything before the execution of the contextual block or not and all. This DTO has 3 options where we can have logArgumentsBefore, logArgumentsAfter and logResult. All 3 have the exact functionality as their name suggests like:
logArgumentsBefore: Whether to log the passed arguments to contextual block, before the execution of the contextual block,
logArgumentsAfter: Whether to log the passed arguments to contextual block, after the completion of the execution of the contextual block,
logResult: Whether to log the result being returned from the function or not.
Now lets see how we will use the above Decorator. Since its a function decorator we will use above the functions, and as expected you will get the callback in the before function and after function.
Line 2: shows us how to use the LogMe decorator with the DTO we defined.
When we call the function getHello of the AppService Class we will get the call in LogMe definition first (in before and after one by one) then the call is transferred to the actual call.
Here is the project code Github Link
Happy Coding :)