I try build block editor with Typescript. My problem is as follows...
I have this:
class A {...}
class B extends A {...}
class C extends A {...}
class D {...}
interface AConstructable {
new (): A;
}
interface AElements {
[name: string]: AConstructable
}
enter code here
const test: AElements = {
blockB: B // ??? this takes B, but have type A :/
}
I need this:
const test: AElements = {
blockB: B // ok!
blockC: C // error
}
const x1 = new test['blockB'](...) // return B class instance
I tried different ways the above is closest but I don't know how to bite it. Is it possible?
In typescript anything which extends a type is assignable to that type. You require that the properties of AElements
are each a constructor that returns an A
. It is fine to return a B
or a C
because all B
s and C
s are also A
s.
The only reason that you have an error on blockC
is because of a missing comma. This code is actually fine:
const test: AElements = {
blockB: B,
blockC: C
}
But that code will still show the value constructed by new test.blockB()
as A
because we haven't preserved any individual information about the properties.
In order to keep the types of the individual property values while also enforcing that they extend A
, you can create test
through an identity function. Using a function allows allows to infer the exact types of the blockB
and blockC
and keep them, while also requiring that the object fits the index signature.
const checkObject = <T extends {}>(obj: T & AElements): T & AElements => obj;
const test = checkObject({
blockB: B,
blockC: C
});
const x1 = new test['blockB']() // return B class instance