javascriptjsdoc

How to use generic types in JSDoc to represent an instance of a (class) type


I am fairly sure this is not possible, but figured someone out there may know more.

I have a simple object factory in JavaScript that I'm using to minimize heap allocs of the same service objects. Something like this:

/**
 * @param {class} cls 
 */
getService(cls) {
  let service = this._services.get(cls); // this._services is a Map
  if(!service) {
    service = Reflect.construct(cls);
    this._services.set(cls, service);
  }
  return service;
}

This is then called with something like

const service = ServiceFactory.getInstance().getService(SomeServiceType)

I'm trying to figure out the JSDoc to accurately represent the type of the return object.

In the above example, the service constant will be an instance of SomeServiceType, but I can't quite figure out the correct JSDoc annotations (if it's even possible)

I've tried all kinds of permutations of using @template, but I think there's some syntax missing from JS, or JSDoc, to allow for this (the lack of a Class type perhaps)

For example, this does not work, but is of the ilk I'm looking for:

/**
 * @template T
 * @param {class<T>} cls 
 * @returns {T}
 */
getService(cls) {
  let service = this._services.get(cls);
  if(!service) {
    service = Reflect.construct(cls);
    this._services.set(cls, service);
  }
  return service;
}

Anyone else trying to make javascript do unnatural things? ;)


Solution

  • You can use new to define class/constructor type and T as a type of class instance

    /**
     * @template T
     * @param {new () => T} cls
     * @returns {T}
     */
    getService(cls) {
      let service = this._services.get(cls);
      if(!service) {
        service = Reflect.construct(cls);
        this._services.set(cls, service);
      }
      return service;
    }