Using Property Decorators in Typescript with a real example
Tags: typescript, javascript, webdev, learning
Published: 2020-05-31 18:29:30

I was talking about [class decorators in typescript](https://dev.to/danywalls/decorators-in-typescript-with-example-part-1-m0f) in my previous post, today is time for properties decorators, how to define and use it for writing clean and elegant code.

### What is Property Decorator
The property decorator is a function, applied to the property declaration in our classes. 

It gets the constructor function of the class and the name of the property as parameters and with this information, we can do funny and cool things, like change the default definition or modify our object instance like an add new properties or change data.


```javascript 
class User {
 @MyDecorator
 password: string;
}
```

### How to create my property decorator.
I build the Min property decorator, it checks if the property has a minimum length, if not the object instance will have a new the errors' property with a message.

I will explain step by step, or you can scroll and read the full code, then let's go.

### 1- Declare the Min function as the decorator.

The decorator is a function, but because we use a factory, the Min function needs the limit number and returns another function that expects the Object and the property key.

```javascript 
function Min(limit: number) {
  return function(target: Object, propertyKey: string) {
```

### 2- Define functions for the getter and setter. 
We need to define 2 functions for handling when the user needs to read or set the value of the property with the decorator.

The getter returns the value of the property himself.
```javascript 
let value : string;
    //the getter of the property to return the value.
    const getter = function() {
      return value;
    };
```
The setter gets the value of the property when using it and handles the validation.
```javascript 
 const setter = function(newVal: string) {

      if(newVal.length < limit) { 
//waiting for Object.define implementation.
      }
```
### 3- Using the Object.defineProperty
The property error needs to be declared using [Object.defineProperty](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperties) a short story about object.defineProperty is it helps to define properties.

The defineProperty methods take 3 parameters: the instance of the object,  the property name, and an object with the configuration like the value or the getter and setter.

```javascript 
 Object.defineProperty(target, 'errors', {
          value: `Your password should be bigger than ${limit}`
        });
```

### 4- Redefine the property using Object.defineProperty and our functions.

The next step is the key, redefine the property with the decorator and set the getter and setter hooks to work with our logic.

```javascript 
 Object.defineProperty(target, propertyKey, {
      get: getter,
      set: setter
    });
```
Done!, you have a clear overview of each statement, then feel free to read the full code.

```javascript
function Min(limit: number) {
  return function(target: Object, propertyKey: string) { 
    let value : string;
    const getter = function() {
      return value;
    };
    const setter = function(newVal: string) {
       if(newVal.length < limit) {
        Object.defineProperty(target, 'errors', {
          value: `Your password should be bigger than ${limit}`
        });
      }
      else {
        value = newVal;
      }      
    }; 
    Object.defineProperty(target, propertyKey, {
      get: getter,
      set: setter
    }); 
  }
}

```
The decorator is ready, the class User will have a password property then using the Min decorator, I set the password minimum length is 8.

```javascript 
class User {
    username: string;
    @Min(8)
    password: string;
    constructor(username: string, password: string){
        this.username = username;
        this.password = password;
    }    
}
```
When the property password is set in the constructor, it calls our decorator and internal getter and setter hooks.

 ```javascript 
    let danyUser = new User("dany", "pass");
    console.log(danyUser);
    console.log(danyUser.errors);
```
Because the password doesn't fit with the requirements, then the error property will be available and contains the value.
```javascript 
[nodemon] starting `node app.js`
User { username: 'dany' }
Your password should be bigger than 8
```
## That's it!
Hopefully, that will give you a bit of help with how and when using Property decorator in Typescript. If you enjoyed this post, share it!

Photo by <a href="https://unsplash.com/@flowforfrank?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Ferenc Almasi</a> on <a href="https://unsplash.com/s/photos/decorators?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Unsplash</a>