Reputation: 9013
I have a class called Model
which wraps a schema class like "Person" and can be successfully instantiated like so:
const people = new Model<Person>(Person, db);
DB is an abstraction to the database and allows the model to interact with the database without needing to know any DB details ... it is likely not terribly relevant for this question but I bring it up as it looks deliciously important.
The redundancy of passing the Person class in twice is annoying and I thought I might be able to create a static method off of Model
called create() which looked like so:
public static create(schema: new () => any, options: IModelOptions = {}) {
const schemaClass = new schema();
const db = options.db || Model.defaultDb;
const logger = options.logger || baseLogger;
const model = new Model<typeof schema>(schema, db, logger);
return model;
}
Where I could then simply instantiate with:
const people = Model.create(Person, { db });
This almost seemed like it was working but it appears that Typescript is a bit off in understanding the generic type being used for the Model
. Am I barking up the wrong tree? Is there a way to achieve what I want to do? If so, what am I doing wrong?
To provide a bit more detail on what is not working ... I find that the generic type information passed in as "T":
export default class Model<T extends BaseSchema> { ... }
is not correctly typing things. So for instance many of the Model's public interface constrain the input to type <T>
but rather than this being "Person" it is resolved to as the constructor function for Person: new () => any
which seems to not constrain at all.
Upvotes: 2
Views: 55
Reputation: 250366
You should make create
generic as well and have the compiler infer the instance type based on the constructor return type, right now you are basically creating Model<typeof Person>
you want Model<Person>
:
class Model<T> {
public constructor(schema: T) {}
public static create<T>(schema: new () => T) {
const schemaClass = new schema();
const model = new Model<T>(schemaClass);
return model;
}
}
class Person {}
let personModel = Model.create(Person) // will be Model<Person>
Upvotes: 2