Using Property Decorators in Typescript with a real example

Using Property Decorators in Typescript with a real example

I was talking about class decorators in Typescript in my previous post; today is time for properties decorators to define and use them 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. We can do funny and marvelous things with this information, like changing the default definition or modifying our object instance, adding new properties, or changing data.

class User {
 @MyDecorator
 password: string;
}

How to create my property decorator.

I build the Min property decorator, and it checks if the property has a minimum length. If not, the object instance will have a new errors' property with a message.

I will explain step by step, or you can scroll and read the complete 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.

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

2- Define functions for the getter and setter.

We need to define two functions for handling when the user needs to read or set the property's value with the decorator.

The getter returns the value of the property himself.

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.

 const setter = function(newVal: string) {

      if(newVal.length < limit) { 
//waiting for Object.define implementation.
      }

3- Using the Object.defineProperty

The property error must be declared using Object.defineProperty a short story about the object.defineProperty is it helps to define properties.

The defineProperty methods take three parameters.

The object's instance, property name, and object the value or the getter and setter.

 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.

 Object.defineProperty(target, propertyKey, {
      get: getter,
      set: setter
    });

Done!, you have a clear overview of each statement, then feel free to read the complete code.

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 minimum password length is 8.

class User {
    username: string;
    @Min(8)
    password: string;
    constructor(username: string, password: string){
        this.username = username;
        this.password = password;
    }    
}

The property password set in the constructor calls our decorator and internal getter and setter hooks.

    let danyUser = new User("dany", "pass");
    console.log(danyUser);
    console.log(danyUser.errors);

Because the password doesn't fit the requirements, the error property will be available and contain the value.

[nodemon] starting `node app.js`
User { username: 'dany' }
Your password should be bigger than 8

Done

Hopefully, that will help you with how and when using Property decorator in Typescript. If you enjoyed this post, share it!

Photo by Ferenc Almasi on Unsplash