menu

JavaScript/Typescript - 16 Topics

DEEP DIVE INTO

JavaScript/Typescript

Topic:Deep dive into decorators

menu

Decorators are a feature in JavaScript, particularly in TypeScript, that allow you to add metadata or behavior to classes, methods, properties, or parameters. They are a way to enhance and modify the behavior of your code without changing its core logic. Decorators are widely used in frameworks like Angular, NestJS, and Mobx to manage things like dependency injection, routing, and state management. Let's dive deep into decorators in JavaScript:

1. Class Decorators:

Class decorators are applied to classes and are typically used for configuration, initialization, or to modify the class behavior. Here's an example of a class decorator in TypeScript:

javascriptfunction logClass(target: Function) {
    console.log(`Class name: ${target.name}`);
}

@logClass
class MyClass {
    constructor() {
        console.log('This is the constructor.');
    }
}

In this example, the @logClass decorator logs the class name when the MyClass class is defined.

2. Method Decorators:

Method decorators are applied to methods within a class. They can be used to intercept, modify, or log method behavior. Here's an example:

javascriptfunction logMethod(target: any, key: string, descriptor: PropertyDescriptor) {
    console.log(`Method called: ${key}`);
    const original = descriptor.value;
    descriptor.value = function () {
        console.log(`Calling method: ${key}`);
        return original.apply(this, arguments);
    };
}

class MyClass {
    @logMethod
    myMethod() {
        console.log('This is myMethod.');
    }
}

const instance = new MyClass();
instance.myMethod();

In this example, the @logMethod decorator logs when the myMethod is called and intercepts its behavior.

3. Property Decorators:

Property decorators are applied to class properties. They are useful for monitoring or controlling access to properties. Here's an example:

javascriptfunction readOnly(target: any, key: string) {
    let value = target[key];

    const getter = function () {
        return value;
    };

    const setter = function (newVal) {
        console.log(`Attempted to set ${key} to ${newVal}, but it's read-only.`);
    };

    Object.defineProperty(target, key, {
        get: getter,
        set: setter,
        enumerable: true,
        configurable: true,
    });
}

class MyClass {
    @readOnly
    readonly myProperty = 'This property is read-only.';
}

const instance = new MyClass();
console.log(instance.myProperty); // 'This property is read-only.'
instance.myProperty = 'New Value'; // Logs that it's read-only.

In this example, the @readOnly decorator makes the myProperty read-only.

4. Parameter Decorators:

Parameter decorators are applied to method parameters. They can be used to modify the parameter values or inject dependencies. Here's a simple example:

javascriptfunction logParameter(target: any, key: string, index: number) {
    console.log(`Parameter at index ${index} in method ${key}`);
}

class MyClass {
    myMethod(@logParameter param1: string, @logParameter param2: number) {
        console.log(`Parameters received: ${param1}, ${param2}`);
    }
}

const instance = new MyClass();
instance.myMethod('Hello', 42);

In this example, the @logParameter decorator logs the method parameters when the myMethod is called.

5. Multiple Decorators:

You can apply multiple decorators to a single element, and they will be executed in the order they are listed:

javascriptfunction firstDecorator(target: any) {
    console.log('First Decorator');
}

function secondDecorator(target: any) {
    console.log('Second Decorator');
}

@firstDecorator
@secondDecorator
class DecoratedClass {
    constructor() {
        console.log('Class Constructor');
    }
}

const instance = new DecoratedClass();

In this example, both firstDecorator and secondDecorator are applied to the DecoratedClass class.

6. Practical Use Cases:

Decorators are widely used in modern JavaScript and TypeScript frameworks for various purposes, including:

  • Dependency injection in frameworks like Angular.

  • Routing in web applications.

  • Validation and serialization of objects.

  • State management in libraries like Mobx.

While decorators are a powerful tool, it's important to use them judiciously and understand the impact they have on your code. They may not be fully standardized in JavaScript and may require transpilers like Babel or TypeScript to work in all environments.

1280 x 720 px