MarkM MarkM - 2 months ago 17
TypeScript Question

Making a generic factory function with access to static properties

I am trying to refactor out a bunch of repeated code and I've hit a bit of a wall. I have a bunch of model classes that represent different types of nodes on a Neo4j db. The classes have a property

static label: string
that corresponds to the type of Node on the DB. I want to use this label, retrieve the nodes and then create instances of the appropriate type.

I have something like this (simplified for this example) that works:

class record {
public static label: string;
public id: number;
}

class RecordType extends record {
label = "Some_DB_Label";

constructor(id: number) {
super()
this.id = id;
}

}

function DBService(klass) {
/* should work for all record subclasses each with different labels */
let label = klass.label;

/* use label to make db query gettig
getting records of type $label */

// create objects from returned information
let id = 10 //<- id from db
return new klass(id)
}


The javascript side of this doesn't have any trouble - this code works fine. I can just call:
DBService(RecordType)
and get the objects. But I'm tossing out all type checking.

I would like to add generic typing to
DBService
. I understand that I can use the constructor function in the signature for a generic like this:

function DBServiceG<T>(klass: { new (id: number): T; }): T


but then I can no longer access the static property. I could also make the static property a regular property on the instance, but then I would need to create an instance to use it - and I can't create the instance until I've made the DB call.

It seems like this should be possible, but I just can't figure it out.

Answer

I guess it is

function DBService<T>(Class: { label: string, new (id: number): T }): T {
  ...
}