打字稿索引签名 class 扩展 class

Typescript index signature class extends class

我尝试使用 Typescript 构建块编辑器。我的问题如下...

我有这个:

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 :/ 
}

我需要这个:

const test: AElements = {
  blockB: B // ok!
  blockC: C // error
}

const x1 = new test['blockB'](...) // return B class instance

我尝试了以上最接近的不同方式,但我不知道如何咬它。可能吗?

在打字稿中,任何扩展类型的东西都可以分配给该类型。您要求 AElements 的每个属性都是 return 一个 A 的构造函数。 return 一个 B 或一个 C 是可以的,因为所有 BC 也是 A

您在 blockC 上出错的唯一原因是缺少逗号。这段代码其实没问题:

const test: AElements = {
  blockB: B,
  blockC: C
}

但是该代码仍会将 new test.blockB() 构造的值显示为 A,因为我们没有保留有关属性的任何单独信息。

为了保留单个 属性 值的类型,同时强制它们扩展 A,您可以通过恒等函数创建 test。使用函数允许推断 blockBblockC 的确切类型并保留它们,同时还要求对象符合索引签名。

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

Typescript Playground Link