Typescript Decorators in Examples

Let’s take a look at the Typescript Decorators that provide a way to add both annotations and a meta-programming syntax for class declarations and members.
⚠️ NOTE Decorators are an experimental feature that may change in future releases.
What will be covered in this article:
- Prerequisites
- What is Decorator
- Simple examples
- Decorators in depth
1. Prerequisites
Before we start exploring Typescript Decorator examples, I’ll be using an empty Node.js typescript project with no additional packages, lints, etc.
All we will need is a typescript
in our dev dependencies in the package.json
file:
First, create an empty folder:

Next, initialize npm project by running npm init -y
in the root dir of your empty project: (-y
flag means that you are answering yes
to all npm questions)

Next, we will need to add typescript
npm package to our dev dependencies:
yarn add typescript -D

Next, we will need to add tsconfig.json
file by running npx tsc — init
in the root of our project:

⚠️NOTE: To enable experimental support for decorators, you must enable the experimentalDecorators
compiler option either on the command line or in your tsconfig.json
file:
Before we will start creating TS Decorators we will need a test subject → I will create a example/User.ts
file that will contain a simple User class:

Now we are ready to create our first decorators 👍
2. What is Decorator
“Decorators provide a way to add both annotations and a meta-programming syntax for class declarations and members. Decorators are a stage 2 proposal for JavaScript and are available as an experimental feature of TypeScript.”
So what are those Decorators, really? As you can see from the gist below it is a function that returns a function of a specific Type:
- ClassDecorator
- PropertyDecorator
- MethodDecorator
- ParameterDecorator
In the next simple examples, we will not cover those return functions and their input parameters, so you could get the main idea behind Decorators first, and after that, we will discuss those params in-depth, be patient 😉
3. Simple examples
So, before we will dive deep into the input parameters of each Decorator let’s take a look at some simple examples…
Class Decorator
We will start with the Class Decorator:

Let’s run this file and see what will happen.
For run use command:
npx ts-node examples/User.ts

⚠️ NOTE: If you are working in WebStorm IDE you create a custom configuration for running your active files. You can check more about it here:
Property Decorator
Property decorators are primarily used to create and attach metadata (it will be covered in the next section 4. Decorators in depth).
Now, let’s create a simple PropertyDecorator:

Result:

Method Decorator
Next, create MethodDecorator:

Result:

Parameter Decorator
Add last but not least — simple Parameter Decorator:

Result:

Multiple Decorators
The awesome thing about all Decorators is that you can put them on top of each other. Method Decorators even allow you to chain return data and modify it:

And see the result:

4. Decorators in depth
Now we can take a closer look at the Decorators return functions and their input params. What additional features do they provide?
Class Decorator
ClassDecorator return function type has only one input parameter → target
:
By using it you can manipulate with the target’s prototype
(we can add an additional field if we want) or we can even create a new instance
of the target class:

… for fixing ts-ignore
we can use this annotation:
(user as User & { isOld: boolean }).isOld
Result:

Property Decorator
Property Decorators are mostly used for adding Metadata.
For our demo purposes, we will need to add reflect-metadata
npm package to our project’s dev dependencies:
yarn add reflect-metadata -D
For metadata we will use Symbol data type, if are not familiar whit that data type — you can check more about it here:
Before we will start coding let me show you what we will get as a result:

Result:

Now let’s see how we can achieve that…
I will remove all previous Decorators and clean-up User class so we could focus on Property Decorator
only:
addReflectMetadata
function looks like this:
If you are not familiar with the reflect-metadata
and how it works under the hood → I will leave console output so you could get the main idea:

Method Decorator
Before a theory tour, I will show you what we can get as a result.
What will be the result of 2+2
?
Nope 🙂:

MethodDecorator is a little bit trickier. The main difficulty can occur when you will face TypedPropertyDescriptor<T>
. Let’s spend some time on a theory:
To make our life easier, and Typescript happier we will use PropertyDescriptor
type for the descriptor
param instead.
⚠️ NOTE: This article is not about Generics and TS Type Guards, but don't use this approach (
TypedPropertyDescriptor<T>
→PropertyDescriptor
) in production, unless you are totally sure.
target
: The prototype of the class;propertyKey
: The name of the method;descriptor
: ATypedPropertyDescriptor<T>
→ (We will usePropertyDescriptor
instead), if you are not familiar with this type you can read about it here:
… but I will show you a quick example of how it works:
Result:

Now, let’s create our method decorator:
…and wrap our “calculate” function with it:

Result:

..and last but not least…
Parameter Decorator
Parameter Decorators are mostly used for adding Metadata exactly the same as Property Decorators used.
I think that after MethorDecorator and PropertyDecorator you get the main idea behind the ParemeterDecorator an how could work without any examples 😉, but I wanted to show you an example from the official docs:
Result of this code fragment:


Now you are totally ready for creating your own Decorators. 🎉 Happy coding!
Source code: