Home > Net >  TypeScript access static property on child class
TypeScript access static property on child class

Time:06-12

I am using TypeScript to represent a complex model in OOP form. There is one parent class Base which sets some values used in almost every class so I don't have repetitive code.

I am using the debug npm package for debug logging, hoping to have logs looking similar to the following:

  mypkg:DataModel:0  This is the first time I ran new DataModel().
  mypkg:OtherMdls:0  And this is the first time I ran new OtherMdls().
  mypkg:DataModel:1  This is a log from the second instance of DataModel.

I am obtaining this result by having the abstract Base class store a static _instanceID property and a private _instanceID property similar to this:

abstract class Base {
  static _instanceID = 0;
  private _instanceID;
  protected _log: debug.Debugger;
  
  constructor() {
    this._instanceID = Base._instanceID  ;
    this._log = debug(`mypkg:${this.constructor.name}:${this._instanceID}`);
  }
}

The value this.constructor.name seems to resolve to whatever the class created's name is, which results in the type of log I want, no matter how many times the class is extended.

The problem is, let's create some extra empty classes:

class A extends Base {}
class B extends Base {}
class C extends Base {}

Now, I am going to create a few of each of these classes and log their _instanceID values.

new A(); // _instanceID = 0 ; expected
new A(); // _instanceID = 1 ; expected
new B(); // _instanceID = 2 ; what? expected 0

I understand the logic here. The Base class is using it's own _instanceID because of this line:

    this._instanceID = Base._instanceID  ;
//                     ^^^^

Now what I want to do is actually increment the static _instanceID on the inheriting class, so that I get results similar to:

new A(); // 0
new A(); // 1
new B(); // 0
new C(); // 0
new B(); // 1
new A(); // 1
new C(); // 1
new C(); // 2

You get the gist by now. How can I fix this?

Also, without passing properties in the super() call, is it possible to make the logs show all inherited classes, similar to mypkg:DataModel:SubModel:Thing:0 or is this too bulky and could it just be mypkg:DataModel:0?

CodePudding user response:

One option would be to reference the constructor for the static id, similar to how you use it to retrieve the name.

The downside is there are currently no good ways to infer the type of the constructor. The linked question shows a few options that serve as a workaround though.

class Base {
  static _instanceID = 0;
  _instanceID;

  constructor() {
    this._instanceID = this.constructor._instanceID  ;
    console.log(this.constructor.name, this._instanceID);
  }
}

class A extends Base {}
class B extends Base {}
class C extends Base {}

new A(); // 0
new A(); // 1
new A(); // 2
new B(); // 0
new B(); // 1
new C(); // 0
new C(); // 1
new C(); // 2

  • Related