Decorators introduces programmers to write the metadata annotation which will help you to introspect your code. Best use-case you find for decorators, will be the cross cutting concerns — Aspect Oriented Programming.
In computing, aspect-oriented programming (AOP) is a programming paradigm that aims to increase modularity by allowing the separation of cross-cutting concerns. It does so by adding additional behavior to existing code (an advice) without modifying the code itself.

Above code — illustrates how declarative the decorators are. Lets cover the decorators in details as below
- What is decorator? and its purpose, types
- Signatures of the decorators
- Method Decorator
- Property Decorator
- Parameter Decorator
- Accessor Decorator
- Class Decorator
- Generalize decorators with Decorator Factory
- Metadata Reflection API
- Conclusion
What is decorator and its purpose, types
A Decorator is a special kind of declaration that can be attached to a class declaration, method, accessor, property, or parameter.
Decorators use the form @expression
, where expression
must evaluate to a function that will be called at run-time with information about the decorated declaration.
It serves the purpose of adding metadata to the existing code in a declarative way.
Types of decorators and its priority of execution are
- Class decorator — Priority 4 (Object Instance, Static)
- Method Decorator — Priority 2 (Object Instance, Static)
- Accessor or Property Decorator — Priority 3 (Object Instance, Static)
- Parameter Decorator — Priority 1 (Object Instance, Static)
Note — If a decorator is applied for parameters of the class constructor then priority for those will be 1. parameter, 2. method, 3. accessor or property decorator — then 4. Constructor parameter decorator will be executed followed by 5. class decorator.

In the code above, we see that a decorator f
and g
returns another function which is a decorator function. f
and g
are called as decorator factories
Decorator factories helps consumer to pass the arguments so the decorator can make use of.
The order of evaluation is from top to bottom and the execution is from bottom to top.
Signatures of the decorators

Method Decorator
From the above signature, method decorator function expects three arguments they are —
- target — current object’s prototype i.e — If Employee is an Object,
Employee.prototype
- propertyKey — name of the method
- descriptor — property descriptor of the method i.e —
Object.getOwnPropertyDescriptor(Employee.prototype, propertyKey)
above code should be self explanatory — Lets see how the compiled JavaScript code looks like
Lets start analyzing Employee function — constructor initialize name
parameters and greet
method attached to the prototype
__decorate([logMethod],Employee.prototype,”greet”)
This is TypeScript auto generated generic method to handle decorator function call with respective argument based on type of decorator.
This function helps to introspect the method call and pave the way for the developer to handle the cross cutting concerns like logging, memorization and applying configuration such as enumerable etc.
In example — we just print what function called with its argument + response.
Note — read the detailed comments under
__decorate
method for understanding the internals
Property Decorator
Property decorator function expects two arguments they are —
- target — current object’s prototype i.e — If Employee is an Object,
Employee.prototype
- propertyKey — name of the property
In the above code, we introspect the property accessibility in the decorator and the compiled code as below.
Parameter Decorator
Parameter decorator function expects three arguments they are —
- target — current object’s prototype i.e — If Employee is an Object,
Employee.prototype
- propertyKey — name of the method
- index — position of the parameter in the argument array
In the code above, we collect all the index or position of the decorated parameters of the methods as metadata and attached to the prototype of the object. Compiled code is below.
As we see earlier, __decorate
function, The __param
function returns a decorator that wraps the parameter decorator.
As we can see when the parameter decorator is invoked, its return is ignored. This means that when the __decorate
function is invoked, its return will not be used to override the parameter.
This is the reason why parameter decorators don’t return.
Accessor Decorator
Accessor is nothing but the getter and setter part for the property in the class declaration.
An Accessor Decorator is declared just before an accessor declaration. The accessor decorator is applied to the Property Descriptor for the accessor and can be used to observe, modify, or replace an accessor’s definitions.
In the code above, we defined two accessor name
and salary
once we configure the enumeration part via decorator. Object acts accordingly. Output is name
will be part of enumeration and the salary
is not.
Note: TypeScript disallows decorating both the
get
andset
accessor for a single member. Instead, all decorators for the member must be applied to the first accessor specified in document order. This is because decorators apply to a Property Descriptor, which combines both theget
andset
accessor, not each declaration separately.
Compile code is below
Class Decorator
The class decorator is applied to the constructor of the class and can be used to observe, modify, or replace a class definition.
The decorator above declares a variable named original
and sets its value to the constructor of the class being decorated.
Then, a utility function named construct
is declared. This function allow us to create instances of a class.
We then create a variable named f
that will be used as the new constructor. This function invokes the original constructor and will also log in console the name of the class being instantiated. Here is where we will add some extra behavior to the original constructor.
The prototype of the original constructor is copied to the prototype of f
to ensure that the instanceof
operator works as expected when we create a new instance of an Employee.
Once the new constructor is ready we just need to return it to finish the class decorator implementation.
Now that the decorator is ready it will log in console the name of a class every time it is instantiated
Compiled code is.
In the compiled version we notice two things different,
- If you see the arguments passed to __decorate its two — array of decorators and the constructor function
- TypeScript compiler is using the return of
__decorate
to override the original constructor.
This is the reason why class decorators must return a constructor function.
Generalize decorators with Decorator Factory
Since each kind of decorator has its own signature to invoke. We can use decorator factory to generalize the invocation of the decorator call
Metadata Reflection API
In order to organize the metadata in a standard way, metadata reflection API can be used [i.e -Reflect
— builtin object]
The name reflection is used to describe code which is able to inspect other code in the same system (or itself).
Reflection is useful for a number of use cases (Composition/Dependency Injection, Run-time Type Assertions, Testing).
In the example above, we have used reflect metadata design key [e.g — design:type
]. For the moment - there are only three available:
- Type metadata uses the metadata key
design:type
. - Parameter type metadata uses the metadata key
design:paramtypes
. - Return type metadata uses the metadata key
design:returntype
.
With the help of reflection we would be able to find following things at run time.
- The name of the entity.
- The type of the entity.
- Which interfaces are implemented by the entity.
- The name and types of the properties of the entity.
- The name and types of the constructor arguments of the entity.
Conclusion
- Decorators are just functions which helps to introspect the code, to annotate and modify classes and properties at design time.
- Decorators are a proposed standard for ECMAScript 2016 by Yehuda Katz.
- We can pass user arguments to the decorator via decorator factories.
- There are 4 types of decorators. They are — Class, Method, Property or Accessor, Parameter Decorators.
- Metadata Reflection API helps to add the metadata information in a standard way to an object and helps to get the design type information at the run time.
You can find all the samples in this Git Repository. Thanks for reading!