← Back to list

Master TypeScript Decorators by Building an Automated Retry Utility

Take a deep dive into Method Decorators. Step-by-step guide on creating a @Retry annotation to automatically re-invoke failed functions.

Vetriselvan Panneerselvam · 2026-04-02 07:51 · 84 claps · 2.1 min read paywalled
#typescript #decorators #custom-decorators #retry #promises
Open on Medium ↗
Wiki topics: 🌐 · Web Development

Master TypeScript Decorators by Building an Automated Retry Utility

H ey devs 👋

This blog is a continuity post for the custom decorator we explored last. While discussing the custom decorators with the team, they asked me to create a few, including one called retry.

Purpose of retry decorator

We are using promises to call the API and doing some async actions at the UI level. We have a use case where we retry the same API calls a few times and return the response. As usual, we know the decorator, so let's start with the custom decorator.

Not a Medium member? You can read the full article for free by clicking here. 🔗

Those who missed my previous blog, please read it.

Creating a file named retry.decorator.ts.

export function Retry(count: number) {
  return function aync(
    target: Object,
    propertyKey: string | undefined,
    descriptor: TypedPropertyDescriptor<any>,
  ) {
    const originalMethod = descriptor.value;
    descriptor.value = async function (...args: any[]) {
      let lastError: any;
      for (let i = 0; i < count; i++) {
        try {
          return await originalMethod.call(this, args);
        } catch (error) {
          lastError = error;
          console.warn(`Attempt ${i + 1} failed. Retrying...`);
        }
      }
      throw lastError;
    };
    return descriptor;
  };
}
  • Retry is a factory function defined to pass the count as a parameter (@Retry(3)).
  • The inner function is what TypeScript calls to modify the class or method.
  • **target**: The class prototype.
  • **propertyKey**: The name of the method being decorated (e.g callApi()).
  • **descriptor**: An object containing the actual function logic.
  • Store the original function in a variable and then override it using a descriptor.value.
  • Based on the count, the loop will be executed; if the promise achieves success, then it will be returned. If an error occurs, it will keep on retrying until the loop is completed. It will throw an error if it fails even though the loop has finished.

Implementation

  @Retry(2)
  async retryPromiseDecorator() {
    if (!this.count) {
      this.count++;
      return Promise.reject('rejected promise');
    } else {
      return Promise.resolve('resolved success');
    }
  }

  async callPromise() {
    const data = await this.retryPromiseDecorator();
    console.log(data);
  }

Note: This specific code uses the Legacy (Experimental) API. If you are using TypeScript 5.0+ without experimentalDecorators: true, the parameters (target, propertyKey, descriptor) would be replaced by a single originalMethod and a context object.

Want to explore the code in detail or try it out locally? Check out the full working example on GitHub: 👉 Source Code: C**ustom-decorator**

Thanks for reading! If this was helpful, consider clapping 👏 and following for more full-stack tips. Do you have questions or suggestions? Drop them in the response below!

✍️ Author: **Vetriselvan Panneerselvam**

👨‍💻 Full Stack Developer | 💡 Code Enthusiast | 📚 Lifelong Learner | ✍️ Tech Blogger | 🌍 Freelance Developer


메타데이터
post_id
c64aed2fe3b2
slug
master-typescript-decorators-by-building-an-automated-retry-utility-c64aed2fe3b2
url
https://medium.com/@vetriselvan_11/master-typescript-decorators-by-building-an-automated-retry-utility-c64aed2fe3b2
canonical_url
https://medium.com/@vetriselvan_11/master-typescript-decorators-by-building-an-automated-retry-utility-c64aed2fe3b2
author_url
https://medium.com/@vetriselvan_11
status
ok
fetched_at
2026-07-11 13:42:50