Answer
Based on @Titian’s answer here, you need to make your findRecord
method into a generic function where T
describes the specific class instance. You use a this
argument as an ignored first argument so that typescript can infer the type of T
based on the value of this
when you call it.
abstract class MyRecord {
constructor(id: number) {
}
static findRecord<T>(this: new (id: number) => T, id: number): T {
return new this(id);
}
}
An Alternative Approach
Personally I have bought into the “inheritance is bad” mantra so I would move shared static
logic into a separate class which can be instantiated for each record type by passing that record’s class as an argument to the constructor.
class RecordFinder<T extends BaseRecord> {
private readonly recordClass: RecordConstructor<T>;
constructor( recordClass: RecordConstructor<T> ) {
this.recordClass = recordClass;
}
find(id: number): T {
return new this.recordClass(id);
}
}
interface BaseRecord {
id: number;
}
type RecordConstructor<T extends BaseRecord> = new (id: number) => T;
Here I am restricting the type of recordClass
based on an interface, so it doesn’t matter whether MyNode
extends MyRecord
or not.
const nodeFinder = new RecordFinder(MyNode);
const node = nodeFinder.find(1);
CLICK HERE to find out more related problems solutions.