Sorry if this has been covered already, but my vocabulary is failing me :(
I'm trying to write a "collection" class, where at instantiation - I give it a "Model" class definition. The collection instance needs to be able to stamp out instances of "Model", but also needs to be able to call static methods on that class.
type Ctor<T> = new (...args: any[]) => T
class Model<T> {
foo: string
bar: string
static myMethod() {}
}
class Extension extends Model<Extension> {
foobar() {}
}
Extension.myMethod() // works
const e = new Extension()
e.foobar() // works
class Collection<T> {
public model: T
constructor(model: T) {
this.model = model
}
getModelInstance() {
// clearly this is problematic
const Model = this.model as unknown as Ctor<T>
return new Model()
}
}
Now the problem becomes when I try to use it:
const c = new Collection(Extension)
c.model.myMethod() // works
const m = c.getModelInstance()
m.foobar() // works at runtime, TS compiler says 'Property 'foobar' does not exist on type 'typeof Extension'.'
So I can redefine my constructor/instance definitions a bit:
class Collection<T> {
public model: Ctor<T>
constructor(model: Ctor<T>) {
this.model = model
}
getModelInstance() {
const Model = this.model
return new Model()
}
}
const c = new Collection(Extension)
c.model.myMethod() // Property 'myMethod' does not exist on type 'Ctor<Extension>'.
const m = c.getModelInstance()
m.foobar() // works
However this doesn't work because Ctor drops my static "context".
Is this possible? It seems like either form I lose type information.