Skip to main content

# decorators

    const decorators: {
      class: {
         Mixins: (...constructors: any[]) => (derivedCtor: any) => void;
         Singleton: <T>(type: T) => SingletonType;
      };
      function: {
         AsyncSingleExecution: (_target: any, _propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
         CacheUntilResolved: (_target: any, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
         Debounce: (delay?: number) => (_target: any, _propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
         ImmutableArgs: (_target: any, _propertyKey: string | symbol, descriptor: PropertyDescriptor) => PropertyDescriptor;
         Memoize: (_target: any, _key: string, descriptor: PropertyDescriptor) => void;
         MemoizeAsync: (_target: any, _propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
         MemoizeSingleArgPrimitive: <T, R>(_target: any, _propertyKey: string, descriptor: TypedPropertyDescriptor<(...args: any[]) => R>) => TypedPropertyDescriptor<(...args: any[]) => R>;
         QueueTask: (_target: unknown, _key: string, descriptor: PropertyDescriptor) => void;
         RetryAsync: (retries?: number, interval?: number, reThrowException?: boolean) => MethodDecorator;
         Throttle: (delay?: number) => (_target: any, _propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
      };
    };

## Type Declaration​

### class​

    class: {
      Mixins: (...constructors: any[]) => (derivedCtor: any) => void;
      Singleton: <T>(type: T) => SingletonType;
    };

#### class.Mixins()​

    Mixins: (...constructors: any[]) => (derivedCtor: any) => void;

A decorator to mix multiple classes into a single class.

##### Parameters​

###### constructors​

...`any`[]

The constructors of the classes to be mixed in.

##### Returns​

A class decorator that mixes the provided classes into the target class.

    (derivedCtor: any): void;

###### Parameters​

###### derivedCtor​

`any`

###### Returns​

`void`

##### Example​

    class A {
      methodA() {
        console.log('A');
      }
    }

    class B {
      methodB() {
        console.log('B');
      }
    }
    // Apply decorator
    // @Mixins(A, B)
    class C {}

    const instance = new C();
    instance.methodA(); // Outputs: 'A'
    instance.methodB(); // Outputs: 'B'

#### class.Singleton()​

    Singleton: <T>(type: T) => SingletonType;

A decorator to make a class a singleton.

##### Type Parameters​

###### T​

`T` extends (...`args`: `any`[]) => `any`

##### Parameters​

###### type​

`T`

The class to be made a singleton.

##### Returns​

`SingletonType`

A proxy that ensures only one instance of the class is created.

##### Example​

    // @Singleton decorator
    class MyClass {
      constructor() {
        console.log('Instance created');
      }
    }

    const instance1 = new MyClass(); // Outputs: 'Instance created'
    const instance2 = new MyClass(); // No output, same instance returned

    console.log(instance1 === instance2); // Outputs: true

### function​

    function: {
      AsyncSingleExecution: (_target: any, _propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
      CacheUntilResolved: (_target: any, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
      Debounce: (delay?: number) => (_target: any, _propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
      ImmutableArgs: (_target: any, _propertyKey: string | symbol, descriptor: PropertyDescriptor) => PropertyDescriptor;
      Memoize: (_target: any, _key: string, descriptor: PropertyDescriptor) => void;
      MemoizeAsync: (_target: any, _propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
      MemoizeSingleArgPrimitive: <T, R>(_target: any, _propertyKey: string, descriptor: TypedPropertyDescriptor<(...args: any[]) => R>) => TypedPropertyDescriptor<(...args: any[]) => R>;
      QueueTask: (_target: unknown, _key: string, descriptor: PropertyDescriptor) => void;
      RetryAsync: (retries?: number, interval?: number, reThrowException?: boolean) => MethodDecorator;
      Throttle: (delay?: number) => (_target: any, _propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;
    };

#### function.AsyncSingleExecution()​

    AsyncSingleExecution: (_target: any, _propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;

AsyncSingleExecution decorator ensures that multiple concurrent calls to an async function with the same arguments will return the same promise instance until it resolves. Once resolved, subsequent calls will trigger a new execution.

##### Parameters​

###### _target​

`any`

###### _propertyKey​

`string`

###### descriptor​

`PropertyDescriptor`

##### Returns​

`PropertyDescriptor`

A function that modifies the property descriptor.

##### Example​

    import { AsyncSingleExecution } from './functionDecorators';

    class Example {
      @AsyncSingleExecution
      async fetchData(id: number) {
        console.log('Fetching data for', id);
        return new Promise(resolve => setTimeout(() => resolve(id), 1000));
      }
    }

    const instance = new Example();
    const promise1 = instance.fetchData(1);
    const promise2 = instance.fetchData(1);

    console.log(promise1 === promise2); // true

// Output: // Fetching data for 1 (only logged once)

    #### function.CacheUntilResolved()

    ```ts
    CacheUntilResolved: (_target: any, propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;

Caches the result of a method until the promise is resolved.

##### Parameters​

###### _target​

`any`

The target object.

###### propertyKey​

`string`

The name of the method.

###### descriptor​

`PropertyDescriptor`

The property descriptor.

##### Returns​

`PropertyDescriptor`

The modified property descriptor.

##### Example​

    class Example {
      // Apply decorator: CacheUntilResolved
      async fetchData() {
        // ...fetch data...
      }
    }

#### function.Debounce()​

    Debounce: (delay?: number) => (_target: any, _propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;

Debounces the method call by the specified delay.

##### Parameters​

###### delay?​

`number` = `300`

The delay in milliseconds.

##### Returns​

A function that modifies the property descriptor.

    (
       _target: any,
       _propertyKey: string,
       descriptor: PropertyDescriptor): PropertyDescriptor;

###### Parameters​

###### _target​

`any`

###### _propertyKey​

`string`

###### descriptor​

`PropertyDescriptor`

###### Returns​

`PropertyDescriptor`

##### Example​

    class Example {
      // Apply decorator: Debounce(500)
      onResize() {
        // ...handle resize...
      }
    }

#### function.ImmutableArgs()​

    ImmutableArgs: (_target: any, _propertyKey: string | symbol, descriptor: PropertyDescriptor) => PropertyDescriptor;

Makes the arguments of a method immutable.

##### Parameters​

###### _target​

`any`

The target object.

###### _propertyKey​

The name of the method.

`string` | `symbol`

###### descriptor​

`PropertyDescriptor`

The property descriptor.

##### Returns​

`PropertyDescriptor`

The modified property descriptor.

##### Example​

    class Example {
      // Apply decorator: ImmutableArgs
      updateData(data: any) {
        // ...update data...
      }
    }

#### function.Memoize()​

    Memoize: (_target: any, _key: string, descriptor: PropertyDescriptor) => void;

Memoizes the result of a method.

##### Parameters​

###### _target​

`any`

The target object.

###### _key​

`string`

The name of the method.

###### descriptor​

`PropertyDescriptor`

The property descriptor.

##### Returns​

`void`

The modified property descriptor.

##### Example​

    class Example {
      // Apply decorator: Memoize
      computeValue(x: number) {
        return x * 2;
      }
    }

#### function.MemoizeAsync()​

    MemoizeAsync: (_target: any, _propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;

Memoizes the result of an async method.

##### Parameters​

###### _target​

`any`

The target object.

###### _propertyKey​

`string`

The name of the method.

###### descriptor​

`PropertyDescriptor`

The property descriptor.

##### Returns​

`PropertyDescriptor`

The modified property descriptor.

##### Example​

    class Example {
      // Apply decorator: MemoizeAsync
      async fetchData() {
        // ...fetch data...
      }
    }

#### function.MemoizeSingleArgPrimitive()​

    MemoizeSingleArgPrimitive: <T, R>(_target: any, _propertyKey: string, descriptor: TypedPropertyDescriptor<(...args: any[]) => R>) => TypedPropertyDescriptor<(...args: any[]) => R>;

Memoizes the result of a function with a single primitive argument or no arguments. Only caches results for functions that take exactly one primitive argument (string, number, boolean, symbol, null, or undefined) or no arguments at all. Uses a simple object as the cache.

##### Type Parameters​

###### T​

`T` extends `string` | `number` | `boolean` | `symbol` | `null` | `undefined`

###### R​

`R`

##### Parameters​

###### _target​

`any`

###### _propertyKey​

`string`

###### descriptor​

`TypedPropertyDescriptor`<(...`args`: `any`[]) => `R`>

##### Returns​

`TypedPropertyDescriptor`<(...`args`: `any`[]) => `R`>

##### Examples​

    // Single primitive argument
    class Example {
      // Apply decorator: MemoizeSingleArgPrimitive
      double(x: number) {
        return x * 2;
      }
    }
    const ex = new Example();
    ex.double(2); // Calls original, returns 4
    ex.double(2); // Returns cached result, 4

    // No arguments
    class ExampleNoArg {
      // Apply decorator: MemoizeSingleArgPrimitive
      getRandom() {
        return Math.random();
      }
    }
    const ex2 = new ExampleNoArg();
    ex2.getRandom(); // Calls original, returns a value
    ex2.getRandom(); // Returns cached value

    // Not cached for non-primitive or multiple arguments
    class ExampleObj {
      // Apply decorator: MemoizeSingleArgPrimitive
      sum(obj: { x: number }) {
        return obj.x + 1;
      }
    }
    const ex3 = new ExampleObj();
    ex3.sum({ x: 1 }); // Calls original
    ex3.sum({ x: 1 }); // Calls original again (not cached)

#### function.QueueTask()​

    QueueTask: (_target: unknown, _key: string, descriptor: PropertyDescriptor) => void;

Queues the method call as a microtask.

##### Parameters​

###### _target​

`unknown`

The target object.

###### _key​

`string`

The name of the method.

###### descriptor​

`PropertyDescriptor`

The property descriptor.

##### Returns​

`void`

The modified property descriptor.

##### Example​

    class Example {
      // Apply decorator: QueueTask
      processTask() {
        // ...process task...
      }
    }

#### function.RetryAsync()​

    RetryAsync: (retries?: number, interval?: number, reThrowException?: boolean) => MethodDecorator;

Retries an async method a specified number of times with a delay between attempts.

##### Parameters​

###### retries?​

`number` = `3`

The number of retry attempts.

###### interval?​

`number` = `2000`

The delay in milliseconds between retries.

###### reThrowException?​

`boolean` = `true`

Whether to rethrow the exception after all retries fail.

##### Returns​

`MethodDecorator`

A method decorator that modifies the property descriptor.

##### Example​

    class Example {
      @RetryAsync(3, 1000, true)
      async fetchData() {
        console.log('Attempting to fetch data...');
        if (Math.random() < 0.7) {
          throw new Error('Fetch failed');
        }
        return 'Data fetched successfully';
      }
    }

    const instance = new Example();
    instance.fetchData().then(console.log).catch(console.error);

    // Output (example):
    // Attempting to fetch data...
    // Attempting to fetch data...
    // Attempting to fetch data...
    // Error: Fetch failed

#### function.Throttle()​

    Throttle: (delay?: number) => (_target: any, _propertyKey: string, descriptor: PropertyDescriptor) => PropertyDescriptor;

Throttles the method call by the specified delay.

##### Parameters​

###### delay?​

`number` = `300`

The delay in milliseconds.

##### Returns​

A function that modifies the property descriptor.

    (
       _target: any,
       _propertyKey: string,
       descriptor: PropertyDescriptor): PropertyDescriptor;

###### Parameters​

###### _target​

`any`

###### _propertyKey​

`string`

###### descriptor​

`PropertyDescriptor`

###### Returns​

`PropertyDescriptor`

##### Example​

    class Example {
      @Throttle(500)
      onScroll() {
        // ...handle scroll...
      }
    }