What I currently have, is a table, which is used in different components, which will have fixed sets of rows for targeting (QA automation), depending on where it is used.
I'm trying to make a generic of those rows for the table, but the code completion isn't working as intended. What am I missing?
class Base {
protected myRoot : string
constructor (root : string) {
this.myRoot = root;
}
get base () {
return "base getter"
}
}
class FixedRows1 extends Base {
get id1 () {
return "id1"
}
}
class FixedRows2 extends Base {
get id2 () {
return "id2"
}
}
class FixedTable <T extends typeof Base> extends Base {
private fixedRows : T
constructor (inRoot : string, inFinalLayer : T) {
super(inRoot)
this.fixedRows = inFinalLayer
}
get rows () {
return new this.fixedRows(this.myRoot)
}
}
const layer = new FixedTable("root", FixedRows1);
layer.rows.base // <---- looking to be able to code complete `.example1`, but currently, only code completes `.base`
CodePudding user response:
The compiler tends to eagerly evaluate property accesses or function calls on unresolved generic types; that means when you write new this.fixedRows(this.myRoot)
, it widens this.fixedRows
to its constraint of typeof Base
, and thus returns Base
. That's not wrong, but it doesn't have enough information for your purposes. If you want to change this, you'll probably need to assert that rows()
returns something else:
get rows() {
return new this.fixedRows(this.myRoot) as InstanceType<T>
}
Here I'm using the InstanceType<T>
utility type to represent the type of the instance constructed by a constructor of type T
.
Now it should behave the way you want:
const layer = new FixedTable("root", FixedRows1);
layer.rows.id1 // okay