Accessing a static member of a generic class from a decorator

I have a decorated class:

@Decorator
class Entity {
    public static member: string[] = [];
}

      

With a decorator:

function Decorator<T extends { new(...args: any[]): Entity }>(constructor: T) {
  return class extends constructor {
    constructor(...args: any[]) {
      super(...args);
      // Do some things
      constructor.prototype.member.map((v: string) => {
        // Do things with the elements of the static array.
      });
    }
  };
}

      

While this works by using constructor.prototype

which is of the type any

, I lose the typechecking of member

which is already in the prototype as an array of strings.

Is there a solution without losing typechecking?

Edit . I've also tested:

function Decorator<T extends { prototype: typeof Entity; new(...args: any[]): Entity; }>(constructor: T) {
  return class extends constructor {
    constructor(...args: any[]) {
      super(...args);
      // Do some things
      constructor.prototype.member.map((v) => {
        // Do things with the elements of the static array.
      });
    }
  };
}

      

but this gives an error on the line @Decorator

:

The 'prototype' property is missing in the 'Entity' type. '

Edit2 : I've tested too:

function Decorator<T extends typeof Entity>(constructor: T) {
  // This works and returns an Entity.
  const x = new constructor({} as any);
  // This doesn't work. Tsc says: 'Type 'T' is not a constructor function type.'
  return class extends constructor {
    constructor(...args: any[]) {
      super(...args);
      // This now works:  
      constructor.member.map((v) => {
        // ...
      });
    }
  };
}

      

but this gives an error on the line @Decorator

:

The 'prototype' property is missing in the 'Entity' type. '

+3


source to share


1 answer


You can do it:

(constructor.prototype as typeof Entity).member...

      

Then you will have type safety like:

(constructor.prototype as typeof Entity).member2..

      

will result in:

Property 'member2' does not exist on type 'typeof Entity'.


Edit

You cannot do this.
Static elements / functions are not part of the prototype, to take what you wanted to do it should look like this:

function Decorator<T extends { prototype: Entity; new(...args: any[]): Entity; }>(constructor: T) { ... }

      

(difference prototype: Entity

, not typeof Entity

) then the error you got will go away.
But then you will get an error:



Property 'member' does not exist on type 'Entity'

Because it is a static member.

It is easy to see in the compiled js class Entity

:

var Entity = (function () {
    function Entity() {
    }
    return Entity;
}());
Entity.member = [];

      

Clearly member

not part of the prototype.

This is why you need to throw it as my original answer says.


2nd edit

Something works here and might be what you need:

type EntityStatic = {
    new (...args: any[]): Entity;
    member: string[];
}

function Decorator(constructor: EntityStatic) {
    ...
}

      

+1


source







All Articles