Issue
We can write our own method in TypeScript to extend a known type class A
. After extension, instance of a new type will have correct type and both fields a
and e
accessible via type system:
class A {
a = "a";
}
function extend(originalType: typeof A){
return class extends originalType {
e = "e"
}
}
const ExtA = extend(A);
const extA = new ExtA();
console.log(extA.a, extA.e); // both .a and .e are accessible.
If we try to extend subclass class B
using same function declaration, clearly, field b
will not be available in type system:
// continued...
class B extends A {
b = "b";
}
const ExtB = extend(B);
const extB = new ExtB();
console.log(extB.a, extB.b, extB.e); // Property 'b' does not exist on type '(Anonymous class)'
This is TS Playground link
I have tried to write a method extend2
and extend3
that would work on any subclass of A
, but without any success.
This were two attempts, using generics and both resulting in TS compilation errors:
// A mixin class must have a constructor with a single rest parameter of type 'any[]'.
function extend2<T extends typeof A>(subclassType: T) {
return class extends subclassType {
e = "e"
}
}
// Class '(Anonymous class)' incorrectly extends base class 'T'.
'(Anonymous class)' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'A'
function extend3<T extends A>(subclassType: new (...args: any[]) => T) {
return class extends subclassType {
e = "e"
}
}
Is there any way to achieve this in TypeScript at this point (v5.3.3)?
Solution
You can do this by making extend
generic as you did with extend2
:
function extend<ClassType extends typeof A>(originalType: ClassType) {
return class extends originalType {
e = "e";
};
}
...but as you discovered, just doing that gives you this error on the return class extends...
statement:
A mixin class must have a constructor with a single rest parameter of type 'any[]'
To fix that, give A
a constructor with a single rest parameter of type any[]
:
class A {
constructor(...args: any[]) {} // <== Needed for `extend` above
a = "a";
}
With those changes, your example works.
Answered By - T.J. Crowder
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.