# 10 Game-Changing Decorator Patterns Every JavaScript Developer Should Know



> Ever looked at @Component, @Injectable, or @Input in Angular and wondered — "Can I make my own decorator magic?"
> 
> 
> If yes, you're about to unlock one of the most elegant and underused features in TypeScript: **decorators**.
> 

This article dives deep into **10 practical and powerful decorator patterns**, not just theory—but **hands-on, demo-style code** you can apply right now in your Angular or vanilla TypeScript projects. We’ll cover class decorators, method decorators, property decorators, and accessor decorators with clarity and purpose.

At the end, you’ll know how to:

- Create and apply custom decorators
- Use decorators to inject behavior, log automatically, validate data, and memoize functions
- Write cleaner, DRY-er, and scalable Angular code
- Think like an advanced frontend developer

Let’s get started.

---

## 1. **Logging Methods Automatically with a Method Decorator**

```jsx
function LogMethod(
  target: Object,
  propertyName: string,
  descriptor: PropertyDescriptor
) {
  const original = descriptor.value;

  descriptor.value = function (...args: any[]) {
    console.log(`Calling ${propertyName} with`, args);
    const result = original.apply(this, args);
    console.log(`Returned from ${propertyName} with`, result);
    return result;
  };
}

```

### Usage:

```jsx
class MathService {
  @LogMethod
  add(a: number, b: number): number {
    return a + b;
  }
}

new MathService().add(2, 3); // Logs input and output

```

---

## 2. **Property Validation Decorator**

```jsx
function Required(target: any, propertyKey: string) {
  let value = target[propertyKey];

  const getter = () => value;
  const setter = (newVal: any) => {
    if (!newVal) {
      throw new Error(`${propertyKey} is required.`);
    }
    value = newVal;
  };

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

```

### Usage:

```jsx
class User {
  @Required
  name: string;

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

new User(""); // Throws error

```

---

## 3. **Creating a Custom Angular Service Decorator**

```jsx
export function SingletonService() {
  return function (target: any) {
    Reflect.defineMetadata('singleton', true, target);
  };
}

```

### Usage:

```jsx
@SingletonService()
@Injectable({ providedIn: 'root' })
export class MyService {}

```

---

## 4. **Memoize Expensive Computations**

```jsx
function Memoize(_: any, key: string, descriptor: PropertyDescriptor) {
  const original = descriptor.value;
  const cache = new Map();

  descriptor.value = function (...args: any[]) {
    const hash = JSON.stringify(args);
    if (cache.has(hash)) {
      return cache.get(hash);
    }
    const result = original.apply(this, args);
    cache.set(hash, result);
    return result;
  };
}

```

### Usage:

```jsx
class MathEngine {
  @Memoize
  fib(n: number): number {
    if (n <= 1) return n;
    return this.fib(n - 1) + this.fib(n - 2);
  }
}

```

---

## 5. **Role-Based Access Control**

```jsx
function Role(role: string) {
  return function (target: any, key: string, descriptor: PropertyDescriptor) {
    const original = descriptor.value;
    descriptor.value = function (...args: any[]) {
      const userRole = 'admin'; // Mock example
      if (userRole !== role) {
        throw new Error(`Unauthorized access to ${key}`);
      }
      return original.apply(this, args);
    };
  };
}

```

### Usage:

```jsx
class AdminPanel {
  @Role('admin')
  deleteUser(userId: string) {
    console.log(`User ${userId} deleted`);
  }
}

```

---

## 6. **Debounce Function Calls**

```jsx
function Debounce(ms: number) {
  return function (_: any, key: string, descriptor: PropertyDescriptor) {
    const original = descriptor.value;
    let timeout: any;

    descriptor.value = function (...args: any[]) {
      clearTimeout(timeout);
      timeout = setTimeout(() => original.apply(this, args), ms);
    };
  };
}

```

### Usage:

```jsx
class SearchBar {
  @Debounce(300)
  onInputChange(value: string) {
    console.log('Search for', value);
  }
}

```

---

## 7. **Readonly Properties with a Property Decorator**

```jsx
function Readonly(target: any, propertyKey: string) {
  Object.defineProperty(target, propertyKey, {
    writable: false,
  });
}

```

### Usage:

```jsx
class Settings {
  @Readonly
  appName = 'MyApp';
}

```

---

## 8. **Auto-Bind Method to Context**

```jsx
function Autobind(_: any, _2: string, descriptor: PropertyDescriptor) {
  const original = descriptor.value;
  return {
    configurable: true,
    get() {
      return original.bind(this);
    },
  };
}

```

### Usage:

```jsx
class ButtonHandler {
  @Autobind
  onClick() {
    console.log('Clicked by', this);
  }
}

```

---

## 9. **Custom @Component Wrapper in Angular**

```jsx
export function EnhancedComponent(metadata: Component) {
  return function (target: any) {
    Component(metadata)(target);
    // Add your enhancements here
  };
}

```

### Usage:

```jsx
@EnhancedComponent({
  selector: 'app-enhanced',
  template: `<p>Enhanced Component</p>`,
})
export class EnhancedComponentDemo {}

```

---

## 10. **Custom Date Formatter Decorator**

```jsx
function FormatDate(_: any, key: string, descriptor: PropertyDescriptor) {
  const original = descriptor.get;

  descriptor.get = function () {
    const result = original!.apply(this);
    return new Date(result).toLocaleDateString();
  };
}

```

### Usage:

```jsx
class Invoice {
  private rawDate = '2025-05-24T12:00:00Z';

  @FormatDate
  get createdAt() {
    return this.rawDate;
  }
}

```

---

## Final Thoughts

Decorators aren’t just for Angular—they’re a **powerful metaprogramming tool** available to all TypeScript developers. Whether you're streamlining UI logic in Angular, reducing boilerplate, or creating testable, reusable utility patterns, decorators can take your code from good to great.

---


### 🎯 Your Turn, Devs!

👀 **Did this article spark new ideas or help solve a real problem?**

💬 I'd love to hear about it!

✅ Are you already using this technique in your Angular or frontend project?

🧠 Got questions, doubts, or your own twist on the approach?

**Drop them in the comments below — let’s learn together!**

---

### 🙌 Let’s Grow Together!

If this article added value to your dev journey:

🔁 **Share it with your team, tech friends, or community** — you never know who might need it right now.

📌 Save it for later and revisit as a quick reference.

---

### 🚀 Follow Me for More Angular & Frontend Goodness:

I regularly share hands-on tutorials, clean code tips, scalable frontend architecture, and real-world problem-solving guides.

- 💼 [**LinkedIn**](https://www.linkedin.com/in/errajatmalik/) — Let’s connect professionally
- 🎥 [**Threads**](https://www.threads.net/@er.rajatmalik) — Short-form frontend insights
- 🐦 [**X (Twitter)**](https://twitter.com/er_rajatmalik) — Developer banter + code snippets
- 👥 [**BlueSky**](http://devrajat.bsky.social/) — Stay up to date on frontend trends
- 🌟 [**GitHub Projects**](https://github.com/malikrajat) — Explore code in action
- 🌐 [**Website**](https://malikrajat.github.io/) — Everything in one place
- 📚 [**Medium Blog**](https://medium.com/@codewithrajat/) — Long-form content and deep-dives
- 💬 [**Dev Blog**](https://dev.to/codewithrajat) — Free Long-form content and deep-dives
- ✉️ [**Substack**](https://codewithrajat.substack.com/) — Weekly frontend stories & curated resources
- 🧩 [**Portfolio**](https://rajatmalik.dev/) — Projects, talks, and recognitions
- ✍️ [**Hashnode**](https://hashnode.com/@codeswithrajat) — Developer blog posts & tech discussions  
- ✍️ [**Reddit**](https://www.reddit.com/user/codewithrajat/submitted/) — Developer blog posts & tech discussions  

---

### 🎉 If you found this article valuable:

- Leave a **👏 Clap**
- Drop a **💬 Comment**
- Hit **🔔 Follow** for more weekly frontend insights

Let’s build cleaner, faster, and smarter web apps — **together**.

**Stay tuned for more Angular tips, patterns, and performance tricks!** 🧪🧠🚀

[**✨ Share Your Thoughts To 📣 Set Your Notification Preference**](https://forms.gle/mdfXEVh3AxYwAsKw5)
