In typescript, for an interface, is there a way to enforce the type of a property to be the "child subclass C, that extends class P"?
example.ts
import { P } from '/path/to/types'
class C extends P {
...
}
types.ts
// `C` is not accessible here
class P {
...
}
interface {
myProp: ???? <-- how to enforce `myProp` is a subclass of P (class, not instance)?
}
Alternatively, I can check Object.getPrototypeOf(myProp.prototype) === P.prototype
, but that is at runtime. Is there a way to enforce this condition via types during compile/checker time?
You can use typeof
to get the type:
class P { ... }
interface Foo {
myProp: typeof P
}
//Usage
class C extends P { ... }
class D { ... }
//Ok
var f: Foo = {
myProp: C
}
// Error
var f2: Foo = {
myProp: D
}
This will ensure that the class specified as the property will be compatible with P
.
Edit
Since Typescript uses structural compatibility, any class that has the same structure as P
will be compatible with typeof P
. If P
has only public members and a small number of members, there may be a risk that another class may unwittingly have the same structure. To ensure that only classes directly inheriting P
are compatible, you can add a private member to P
that makes P
incompatible with other classes (even ones with the same structure, different declarations of private fields are not compatible with each other)
class P { private nonStructural:true }
interface Foo {
myProp: typeof P
}
//Usage
class C extends P { }
class D { private nonStructural:true }
//Ok
var f: Foo = {
myProp: C
}
// Error
var f2: Foo = {
myProp: D
}