Mapagam
  • JavaScript 
  • Web APIs 
  • TypeScript 
  • React 

Understanding TypeScript Decorators: A Step-by-Step Guide

Posted on April 21, 2025 • 7 min read • 1,284 words
Share via
Mapagam
Link copied to clipboard

Learn how TypeScript decorators enhance your code with classes, methods, and properties. Practical examples and best practices included.

On this page
1. What Are TypeScript Decorators? 1.1. The Basics of Decorators 1.2. Enabling Decorators in TypeScript 2. Types of Decorators 2.1. Class Decorators 2.2. Method Decorators 2.3. Property Decorators 2.4. Parameter Decorators 3. How Decorators Work Behind the Scenes 3.1. Transpiled Code Example 4. Practical Applications of TypeScript Decorators 4.1. Dependency Injection in Angular 4.2. Validation and Logging 5. Pitfalls and Best Practices 5.1. Avoid Overusing Decorators 5.2. Be Careful with Prototype Manipulations 5.3. Ensure Compatibility with Tools 6. Conclusion Key Takeaways:

TypeScript decorators offer a powerful and flexible way to add behavior to classes and their members. They are widely used in Angular, and as a TypeScript feature, they provide a way to enhance object-oriented programming (OOP) paradigms in modern JavaScript applications. Whether you’re working on a React application, building a Node.js API, or just exploring TypeScript, decorators are a valuable tool in your toolbox. This article provides a step-by-step guide to understanding TypeScript decorators and how to leverage them in your development.

1. What Are TypeScript Decorators?

Decorators in TypeScript are special functions that allow you to modify or annotate classes, methods, properties, and parameters. They act as metadata or functions that are attached to a class, method, accessor, or property to add extra functionality, such as logging, validation, or other behaviors.

Decorators provide a more expressive and flexible way of writing reusable code by abstracting out common functionality, allowing you to inject behavior without manually modifying the core logic of the class or method.

1.1. The Basics of Decorators

Decorators are defined as functions, and they are prefixed with the @ symbol. They can be attached to:

  • Class Decorators: Applied to a class definition.
  • Method Decorators: Applied to a method within a class.
  • Property Decorators: Applied to class properties.
  • Parameter Decorators: Applied to method parameters.

Decorators can be chained and combined to achieve more complex behaviors. For example, you can combine a log decorator and an auth decorator to both log method calls and check authentication.

1.2. Enabling Decorators in TypeScript

In TypeScript, decorators are an experimental feature, so they must be explicitly enabled in your tsconfig.json file. Add the following to the compilerOptions section:

{
  "compilerOptions": {
    "experimentalDecorators": true
  }
}

2. Types of Decorators

TypeScript supports several types of decorators. Let’s dive deeper into each one and understand how they work.

2.1. Class Decorators

Class decorators are applied to the class constructor function. These decorators can modify the class itself or its prototype.

Here’s an example of a simple class decorator:

function logClass(target: Function) {
  console.log(`Class ${target.name} is being created.`);
}

@logClass
class MyClass {
  constructor(public name: string) {}
}

const obj = new MyClass("Test");

In this example, the logClass decorator logs a message when the MyClass class is created.

2.2. Method Decorators

Method decorators are applied to a method within a class. They take three arguments:

  1. The target object (the prototype of the class).
  2. The name of the method.
  3. The descriptor of the method (which allows modification of the method).

Example:

function logMethod(target: any, key: string, descriptor: PropertyDescriptor) {
  const originalMethod = descriptor.value;
  descriptor.value = function(...args: any[]) {
    console.log(`Calling ${key} with arguments: ${args}`);
    return originalMethod.apply(this, args);
  };
}

class MyClass {
  @logMethod
  sayHello(name: string) {
    console.log(`Hello, ${name}!`);
  }
}

const obj = new MyClass();
obj.sayHello("Alice");

In this example, the logMethod decorator logs the arguments passed to the sayHello method.

2.3. Property Decorators

Property decorators allow you to add metadata to class properties. They are defined in a similar way to method decorators, but they operate on the property rather than the method.

function logProperty(target: any, key: string) {
  let value: any;
  const getter = () => value;
  const setter = (newValue: any) => {
    console.log(`Setting ${key} to ${newValue}`);
    value = newValue;
  };
  Object.defineProperty(target, key, { get: getter, set: setter });
}

class MyClass {
  @logProperty
  name: string;

  constructor(name: string) {
    this.name = name;
  }
}

const obj = new MyClass("Alice");
obj.name = "Bob"; // Logs: Setting name to Bob

The logProperty decorator intercepts setting a property and logs the new value whenever the name property is changed.

2.4. Parameter Decorators

Parameter decorators are applied to method parameters. These are useful when you need to add metadata to parameters, such as validation checks or logging.

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

class MyClass {
  greet(@logParameter name: string) {
    console.log(`Hello, ${name}!`);
  }
}

const obj = new MyClass();
obj.greet("Alice");

In this example, the logParameter decorator logs the index of the parameter in the method.

3. How Decorators Work Behind the Scenes

TypeScript decorators are implemented using JavaScript’s Reflect API, which provides metadata reflection. When a decorator is applied to a class or method, TypeScript generates metadata that is stored in the JavaScript code. This metadata can then be accessed at runtime.

Understanding how decorators are transpiled in JavaScript can be helpful in debugging and optimizing your code. Let’s look at an example of what TypeScript generates when decorators are used.

3.1. Transpiled Code Example

Here’s a comparison of how a decorator works in TypeScript versus the JavaScript that gets generated after compilation.

TypeScript Code:

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

@logClass
class MyClass {}

Transpiled JavaScript Code:

function logClass(target) {
  console.log(`Class ${target.name} created.`);
}

let MyClass = class {};
logClass(MyClass);

In the transpiled JavaScript code, the decorator is applied directly to the class after it is defined.

4. Practical Applications of TypeScript Decorators

Decorators offer a range of practical use cases, particularly in large-scale applications. Let’s discuss a few common real-world scenarios where decorators shine.

4.1. Dependency Injection in Angular

In Angular, decorators are heavily used for dependency injection, routing, and other features. Here’s an example of a service decorated with @Injectable:

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class MyService {
  constructor() {
    console.log('Service Initialized');
  }
}

In this case, @Injectable is used to tell Angular that the MyService class can be injected as a dependency into other components.

4.2. Validation and Logging

You can use decorators for adding validation or logging mechanisms across multiple methods or properties. For example:

function required(target: any, key: string) {
  let value: any;
  const getter = () => value;
  const setter = (newValue: any) => {
    if (!newValue) {
      console.error(`${key} is required`);
    }
    value = newValue;
  };
  Object.defineProperty(target, key, { get: getter, set: setter });
}

class User {
  @required
  username: string;
}

const user = new User();
user.username = ""; // Logs: username is required

Here, the required decorator ensures that the username property is set to a valid value.

5. Pitfalls and Best Practices

While decorators are powerful, they can also introduce complexity and potential pitfalls if not used properly. Here are some best practices to keep in mind:

5.1. Avoid Overusing Decorators

Decorators can make your code cleaner by abstracting away repetitive functionality, but using too many decorators can lead to difficult-to-debug code. Use them where appropriate, but don’t overcomplicate simple logic.

5.2. Be Careful with Prototype Manipulations

Decorators can modify class prototypes and methods. While this is often useful, it can also lead to unintended consequences if not handled properly. Make sure to keep track of changes to method descriptors and properties.

5.3. Ensure Compatibility with Tools

Since decorators are an experimental feature in TypeScript, make sure your build tools (e.g., Webpack, Babel) support them properly. Also, ensure that other libraries or frameworks you use can handle decorators without issues.

6. Conclusion

TypeScript decorators offer a sophisticated way to enhance your code by adding behavior to classes and their members. By using decorators, you can add functionality like logging, validation, and dependency injection in a modular and reusable manner. Decorators are a powerful tool in modern JavaScript development, especially when building large-scale applications.

Key Takeaways:

  • Decorators are functions that add metadata and behavior to classes, methods, properties, and parameters.
  • You need to enable decorators in TypeScript using the experimentalDecorators option.
  • Common types of decorators include class, method, property, and parameter decorators.
  • Decorators can be used to implement powerful features like logging, validation, and dependency injection.
  • Be mindful of the potential complexity and ensure decorators are used appropriately to avoid overcomplicating code.

With this foundational understanding, you’re now equipped to start leveraging TypeScript decorators in your projects and enhance your development workflow.

TypeScript Decorators   TypeScript Tutorial   JavaScript Decorators   TypeScript Best Practices   Angular Decorators  
TypeScript Decorators   TypeScript Tutorial   JavaScript Decorators   TypeScript Best Practices   Angular Decorators  
How TypeScript’s Type Inference Works (And Why It’s a Game-Changer) 

More Reading!

  1. Master TypeScript Generics: A Beginner’s Guide with Real-World Examples
  2. TypeScript Tuples: What They Are and How to Use Them
  3. How to Work with Arrays in TypeScript
  4. How to Use TypeScript Objects Like a Pro
  5. Mastering TypeScript Functions: The Ultimate Guide
On this page:
1. What Are TypeScript Decorators? 1.1. The Basics of Decorators 1.2. Enabling Decorators in TypeScript 2. Types of Decorators 2.1. Class Decorators 2.2. Method Decorators 2.3. Property Decorators 2.4. Parameter Decorators 3. How Decorators Work Behind the Scenes 3.1. Transpiled Code Example 4. Practical Applications of TypeScript Decorators 4.1. Dependency Injection in Angular 4.2. Validation and Logging 5. Pitfalls and Best Practices 5.1. Avoid Overusing Decorators 5.2. Be Careful with Prototype Manipulations 5.3. Ensure Compatibility with Tools 6. Conclusion Key Takeaways:
Follow me

I work on everything coding and technology

   
Mapagam
Mapagam is your go-to resource for all things related to frontend development. From the latest frameworks and libraries to tips, tutorials, and best practices, we dive deep into the ever-evolving world of web technologies.
Licensed under Creative Commons (CC BY-NC-SA 4.0).
 
Frontend
JavaScript 
Web Api 
TypeScript 
React 
Social
Linkedin 
Github 
Mapagam
Code copied to clipboard