I am extending a class which comes from an external library and is sadly not typed. To makes matters even more complicated, it's instantiation is done via a static method in the untyped class. The change of this as it stands is not an option. It would look something like this:
class MyUntypedClass {
constructor (context) {
this.someAttribute = ''
this.someOtherAttribute = ''
}
static createNewInstanceWithStuff () {
// do a bunch of stuff prior to creating the instance
const instance = new this(context)
return instance
}
}
As mentioned I then extend it and make sure to type my methods:
class MyTypedClass extends MyUntypedClass {
private myNewAttribute = ''
constructor() {
super({ stuff })
this.myNewAttribute = myNewAttribute
}
private myNewMethod (param: string, otherParam: number): string {
// do stuff
}
}
However, I must instantiate it via the static method from MyUntypedClass
, and I end up losing the types I had written for my methods. Code looks something like this:
const instance = MyTypedClass.createNewInstanceWithStuff()
const value = instance.myNewMethod('some string', 123) // if I try to check the params or return type it is any
Is there anyway to type my methods whenever the instance is created from the untyped parent class?
CodePudding user response:
If you want the static createNewInstanceWithStuff
method of MyTypedClass
to be of a more specific type than that of the MyUntypedClass
but you don't want to change the runtime behavior, you can use the declare
property modifier to tell the compiler that. This will have no effect on the emitted JavaScript. It looks like this:
class MyTypedClass extends MyUntypedClass {
/* ... */
declare static createNewInstanceWithStuff: () => MyTypedClass; // <-- declare this
/* ... */
}
Note that you have to use a function-typed field annotation instead of a method, because the declare
property modifier is not currently supported for methods (see microsoft/TypeScript#38008 for the relevant feature request).
Now it should work as expected:
const instance = MyTypedClass.createNewInstanceWithStuff();
// const instance: MyTypedClass
const value = instance.myNewMethod('some string', 123)
// const value: string;