Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Class Decorator in Typescript

I'm trying to understand how class decorators work in Typescript when we wish to replace the constructor. I've seen this demo:

const log = <T>(originalConstructor: new(...args: any[]) => T) => {
    function newConstructor(... args) {
        console.log("Arguments: ", args.join(", "));
        new originalConstructor(args);
    }
    newConstructor.prototype = originalConstructor.prototype;
    return newConstructor;
}

@log
class Pet {
    constructor(name: string, age: number) {}
}

new Pet("Azor", 12);
//Arguments: Azor, 12

Everything is understood but this line:

newConstructor.prototype = originalConstructor.prototype;

Why do we do that?

like image 205
RiskX Avatar asked Oct 17 '22 11:10

RiskX


People also ask

What is class decorator in TypeScript?

A Decorator is a special kind of declaration that can be attached to a class declaration, method, accessor, property, or parameter. Decorators use the form @expression , where expression must evaluate to a function that will be called at runtime with information about the decorated declaration.

What is the use of decorator in TypeScript?

A Decorator is a special kind of declaration that can be applied to classes, methods, accessor, property, or parameter. Decorators are simply functions that are prefixed @expression symbol, where expression must evaluate to a function that will be called at runtime with information about the decorated declaration.

What is class decorators in Angular?

The whole purpose of Angular decorators is to store metadata about a class, method, or property. When you configure a component, you are providing a metadata for that class that tells Angular that you have a component, and that component has a specific configuration.

How do you use TS decorators?

In TypeScript, you can create decorators using the special syntax @expression , where expression is a function that will be called automatically during runtime with details about the target of the decorator. The target of a decorator depends on where you add them.


1 Answers

The classes like:

class Pet {
    constructor(name: string, age: number) {}
    dosomething() {
        console.log("Something...");
    }
}

Are compiled into functions when targeting ES5:

var Pet = (function () {
    function Pet(name, age) {
    }
    Pet.prototype.dosomething = function () {
        console.log("Something...");
    };
    return Pet;
}());

As you can seem when we use functions to define classes. The methods are added to the function's prototype.

This means that if you are going to create a new constructor (new function) you need to copy all the methods (the prototype) from the old object:

function logClass(target: any) {

  // save a reference to the original constructor
  const original = target;

  // a utility function to generate instances of a class
  function construct(constructor: any, args: any[]) {
    const c: any = function () {
      return constructor.apply(this, args);
    };
    c.prototype = constructor.prototype;
    return new c();
  }

  // the new constructor behaviour
  const newConstructor: any = function (...args: any[]) {
    console.log("New: " + original.name);
    return construct(original, args);
  };

  // copy prototype so intanceof operator still works
  newConstructor.prototype = original.prototype;

  // return new constructor (will override original)
  return newConstructor;
}

You can learn more at "Decorators & metadata reflection in TypeScript: From Novice to Expert (Part I)"

Update

Please refer to https://github.com/remojansen/LearningTypeScript/tree/master/chapters/chapter_08 for a more recent version.

like image 167
Remo H. Jansen Avatar answered Oct 21 '22 07:10

Remo H. Jansen