Closed
Description
Sorry for the crap title, I'm not entirely sure what is going on but I think it's a bug. I also think this is somewhat related to #5449 but am unsure.
Library Example:
export interface InstanceConstructor<T extends BaseModel> {
new(fac: Factory<T>): T;
}
export class Factory<T extends BaseModel> {
constructor(private cls: InstanceConstructor<T>) {}
get() {
return new this.cls(this);
}
}
export class BaseModel {
constructor(private fac: Factory<this>) {}
refresh() {
// get returns a new instance, but it should be of
// type Model, not BaseModel.
return this.fac.get();
}
}
User Code Example:
export class Model extends BaseModel {
do() {
return true;
}
}
// Kinda sucks that Factory cannot infer the "Model" type
let f = new Factory<Model>(Model);
let a = f.get();
let b = a.refresh();
The issue that the compiler complains about is as follows:
error TS2345: Argument of type 'typeof Model' is not assignable to parameter of type 'InstanceConstructor<Model>'.
Types of parameters 'api' and 'api' are incompatible.
Type 'Factory<this>' is not assignable to type 'Factory<Model>'.
Type 'this' is not assignable to type 'Model'.
Type 'BaseModel' is not assignable to type 'Model'.
Property 'do' is missing in type 'BaseModel'.
If I change the extended model to be specific it errors in different way, but same theme.
export class Model extends BaseModel {
constructor(fac: Factory<Model>) {
super(fac);
}
do() {
return true;
}
}
error TS2345: Argument of type 'Factory<Model>' is not assignable to parameter of type 'Factory<this>'.
Type 'Model' is not assignable to type 'this'.
I think the reason is because this
isn't being polymorphic in either the template or the constructor. When this
is analyzed in the constructor of BaseModel
it seems to stick with that context.
I initially posted about the use of polymorphic this
which was answered by @RyanCavanaugh http://stackoverflow.com/questions/33443793/create-a-generic-factory-in-typescript