Developed By
Gautam Kumar - Full stack developer
DEEP DIVE INTO
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:
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.
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.
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.
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.
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.
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.