Given
class Foo {
x = 1;
y = 2;
}
class Bar extends Foo {
override x = 11;
z = 3;
}
Is it possible to derive Foo
given Bar
automatically? Like Superclass<Bar> === Foo
?
Given
class Foo {
x = 1;
y = 2;
}
class Bar extends Foo {
override x = 11;
z = 3;
}
Is it possible to derive Foo
given Bar
automatically? Like Superclass<Bar> === Foo
?
1 Answer
Reset to default 0There's unfortunately no way to do this that doesn't involve actually mentioning Foo
manually.
It's not possible to write a utility type that accepts the instance type Bar
and produces Foo
from it, so there's no way to write type Superclass<T> = ⋯
. That's because the type named Bar
doesn't really know anything about Foo
. TypeScript's type system is structural and not nominal. TypeScript cares about the shape or structure of a type, such as the properties of an object type. It does not care about the name or the declaration of the type. Your Bar
is therefore completely equivalent to
interface MyBar {
x: number,
y: number,
z: number
}
var v: Bar;
var v: MyBar; // okay
(Note that TypeScript allows you to redeclare the var
v
as both Bar
and MyBar
, which is evidence that it considers those to be identical types. Otherwise there would have been a compiler error saying that subsequent declarations must be the same type.) And since the MyBar
type doesn't have anything to do with Foo
(there's no way to discern which, if any, of the properties of MyBar
might have come from somewhere else), then neither does the Bar
type.
Structural typing places some limits on the kinds of things you can do in the type system, and this is one such limit.
One might hope that at least inside of the body of the Bar
class
statement you'd be able to refer to the type of super
programmatically, but this is also not possible. There is no "polymorphic super
type" that works like the polymorphic this
type. I didn't find any existing feature requests in the TypeScript GitHub repository issues; if you really need this you might consider filing a request, but given that the workaround today is just "use Foo
instead of super
" and nobody else is asking for this, it's unlikely that such a request would be implemented.
Playground link to code
any
instead ofFoo
– Alexander Nenashev Commented Mar 3 at 13:17Bar
doesn't contain any metadata about what it might be extended from. Indeed, TS's structural type system makes such questions somewhat meaningless, since it's the shape of the types that matter, not their names or declaration sites. The typeBar
is equivalent to{ x: number, y: number, z: number }
, and that type doesn't "know" anythingFoo
. Does that fully address the question (even though it's not what you want to hear?) If so I'll write an answer or find a duplicate; if not, what's missing? – jcalz Commented Mar 3 at 14:53