Utilizing Polymorphic this
may not fully solve your problem here; unlike Java, there's no explicit way in TypeScript to declare a class as final
. This means that the polymorphic this
might have to refer to a more precise type within an unknown subclass context. For instance:
class Foo extends Derived {
map(val: number) {
return "oops";
}
}
new Foo(7).getDefaultVal().toUpperCase(); // error at runtime
In this scenario, even after extending Derived
with no compile-time issues, calling Foo.getDefaultVal()
relies on inheriting from Derived
, where the expected return type is supposed to be DeriveMapVal<this, number>
, and in this case, this
should resolve to Foo
. As a result, DeriveMapVal<Foo, number>
points to a string
, while Foo
's implementation just returns a number
, leading to a compiler error due to the inability to verify if number
is assignable to DeriveMapVal<this, number>
.
To address this issue, one possible solution involves refining the subclass implementation to explicitly reference the self-class rather than relying on this
:
class Derived extends Generic<number> {
getDefaultVal(): DeriveMapVal<Derived, number> {
return 0; // valid
}
}
This approach may provide a resolution, despite the fact that you can still extend
Derived</code as usual, and the compiler correctly identifies that <code>Foo
is not compatible with
Derived
:
class Foo extends Derived {
map(val: number) {
return "oops";
}
}
new Foo(7).getDefaultVal().toUpperCase(); // now also produces a compile-time error
const d: Derived = new Foo(10); // error
const g: Generic<number> = new Foo(20); // error
The declaration class Foo extends Derived
does not necessarily ensure that Foo extends Derived
is true. It's quite peculiar behavior. If you are able to handle this limitation, approaching it in such a manner could offer a path forward.
Hopefully, this provides some insights and assistance for your situation. Best of luck!
Click here to view the code in Playground