DEV Community

Cover image for Decorate Your TypeScript Code
MohammedFarhoud
MohammedFarhoud

Posted on • Updated on

Decorate Your TypeScript Code

Remember the first time I saw the '@' symbol in my first Angular application, what is this and why do we need it?
The combination of @ and another word forms a term called decorator.

Decorator is a special kind of declaration or attribute that can be attached to a class, method, property or parameter to change the way they behave. It is considered as a design pattern.

Before we dive into decorators and their magic influence, there are two things that worth mentioning:

  1. In typescript, there are no built-in decorators, you must build your own.

  2. Before we build a decorator, we must enable a compiler option, since decorators are still experimental and their implementation may change in the future:
    In your tsconfig.json file uncomment the "experimentalDecorators" setting:

Compiler option

Decorator Factories:

To build our own decorator, we need a factory function that returns the expression to be executed by the decorator at runtime

Class Decorators:

If you are familiar with Angular look at the next example, if not don't worry you will build your decorator soon:
A component is just a class but how can Angular know it is a component not an ordinary class.
Yes the answer is decorator, Angular has many built in decorators, one of them is @Component which tells angular that "hey, I am a component!"

import { Component } from '@angular/core';

@Component({
  selector: 'app-server',
  templateUrl: './server.component.html',
  styleUrls: ['./server.component.css']
})
export class ServerComponent {

}
Enter fullscreen mode Exit fullscreen mode

As we have said, typescript has no built-in decorators but for a component to work you must import it from angular core components.

Behind the scenes a decorator is just a function that is called by JavaScript runtime.
To build or own class decorator we need a function. To inform the function that it is a class decorator, pass constructor as a parameter. Do NOT forget the type Function, we use TypeScript!.

function Component (constructor: Function) {
    console.log('Hey! I am a component.');
}

@Component
class OurNewComponent {

}
Enter fullscreen mode Exit fullscreen mode

Let's try this. Now we can say welcome to our new component.

result from decorator

We can improve our component by making a parametrized decorator:

type ComponentOptions = {
    selector?: String,
    templateUrl?: String
    stylesUrl?: [String]
}

function Component (options: ComponentOptions) {
    return (constructor: Function) => {
        constructor.prototype.options = options;        
    }
}

@Component({
    selector:'my-app',
    templateUrl: 'app.html',
    stylesUrl: ['app.css']
})
class OurNewComponent {

}
Enter fullscreen mode Exit fullscreen mode

Looks like our angular component decorator, doesn't it?

Method Decorators:

We can add a decorator before a method to add a logic before, after it or even change the entire behavior of the function.

function Server(target: any, methodName: string, descriptor: PropertyDescriptor) {
    const originalMethod =  descriptor.value as Function;
    descriptor.value = function (...args: any) {
        console.log(`Server is being started.`);
        originalMethod.call(this, ...args)
        console.log(`Server status has been updated!`);
    }
}

class MySever {
    @Server
    getServerStatus(status: string, port: number) {
        console.log(`server is currently ${status} and running on port ${port}.`);
    }
}
Enter fullscreen mode Exit fullscreen mode

Before @Server decorator, the function just prints a single line but after adding this decorator it has changed the behavior of the function leading to the following result:

method decorator result

There is something I want to mention here. As you know, we try not to use any as much as possible but in this case the compiler expects this type from us.

As we have learned about decorators, how can frameworks like angular use decorators and how we can build our own class and function ones. You must have realized how powerful decorators are and how they can be used to change code behavoir.

We covered both class and method decorators but there are still accessor, property, class decorators and how to use them with Express.js. So, if you like to decorate your code more stay tuned!

Top comments (0)