4

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?

1 Answer 1

3

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

Sign up to request clarification or add additional context in comments.

1 Comment

Ahah! That explains where my problem was. I had found this solution, but I was confused why B.constructor._instanceID was undefined... but I realized, just now, I needed to execute (new B()).constructor._instanceID instead!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.