【发布时间】:2021-05-08 22:01:49
【问题描述】:
我需要帮助来弄清楚如何在 typescript 中正确地断言类型。
我正在使用的代码让 rn 感到困惑(我认为我让它变得比它需要的更复杂,哈哈 :3),所以我将简要介绍一下我正在尝试完成的工作。
所以基本上我有一个实现 IAbstractFactory 接口的 ConcreteFactory 类。 ConcreteFactory 类可以创建/生成 3 个不同的具体类 BaseDocument、DocumentA 和 DocumentB。
interface IAbstractFactory{
createBaseDocument(): Promise<IAbstractDocument>;
createDocumentA(): Promise<IAbstractDocument>;
createDocumentB(): Promise<IAbstractDocument>;
}
class ConcreteFactory implements IAbstractFactory{
public async createBaseDocument(): Promise<IAbstractDocument> {
return new BaseDocument();
}
public async createDocumentA(): Promise<IAbstractDocument> {
return new DocumentA();
}
public async createDocumentB(): Promise<IAbstractDocument> {
return new DocumentB();
}
}
请注意,只有 Document 类实现了 IAbstractDocument 接口。 DocumentA 和 DocumentB 都扩展了 BaseDocument。
interface IAbstractDocument{
methodBase(){};
}
class BaseDocument implements IAbstractDocument{
methodBase(){};
}
// uses all of BaseDocuments functions but has some extra functions that DocumentB does not have
class DocumentA extends BaseDocument{
methodBase(){};
methodA(){}; // not implemented in IAbstractDocument, throws error
}
// uses all of BaseDocuments functions but has some extra functions that DocumentA does not have
class DocumentB extends BaseDocument{
methodBase(){};
methodB(){}; // not implemented in IAbstractDocument, throws error
}
我还有一个名为 Tree 的类,它将构建一棵树,每个节点的类型都是 IAbstractDocument
class Tree{
rootNode:IAbstractDocument; // Realistically of type DocumentA or DocumentB, IAbstractDocument is throwing error, explained below
nodes: IAbstractDocument[]; // Realistically of type DocumentA or DocumentB, IAbstractDocument is throwing error, explained below
// this function will create factory and the factory will create DocumentA or Document B
createDocument(){}
addDocument()
}
我的目标是创建一个文档树。规则是 DocumentA 可以包含子节点,类型为 DocumentA 或 DocumentB,但 DocumentB 不能有任何子节点(它们只能是叶节点)。
问题是:
虽然 DocumentA 和 DocumentB 都扩展了 BaseDocument。在 Tree 类中,它们在 IAbstractDocument 类型下定义(我这样做是因为我认为这就是 ConcreteFactory 返回的内容)。所以现在我得到一个错误,DocumentA 和 DocumentB(分别是methodA 和methodB)中的唯一函数没有在IAbstractDocument 中定义。所以我不能在 Tree 类中使用它们,我只能使用 methodBase()。
我的问题是:
如何将 DocumentA 和 DocumentB 视为相同但不同的类型?它们都应该被视为 中的文档节点树,但它们具有与它们相关的不同功能。
任何帮助将不胜感激,谢谢!
【问题讨论】:
-
请考虑修改这里的代码以构成一个minimal reproducible example 适合放入像The TypeScript Playground 这样的独立IDE,以便其他人可以重现您的问题(您所说的任何错误都应该是明显的) 并且只有您的问题(应删除其他错误,如拼写错误或未声明的依赖项)。如果我可以立即开始解决问题而不必先解决问题,那么提供帮助会容易得多。
-
我不知道在这里对
Tree说什么;nodes不应该是其他Tree实例吗?如果您对子/叶区分有如此不同的要求,您可能希望Tree本身是可子类化的,并具有DocumentATree和DocumentBTree。 -
我倾向于使用union types 并避免使用一般的基本/抽象版本。 this 是否为您工作或为您提供指导?如果是这样,我会写一个答案;如果不是,请详细说明您的问题。
-
对不起,如果我没有给出一个可重现的例子,我应该考虑一下。 Union 类型确实有意义,我认为这就是我需要的答案。谢谢!但是,让节点成为其他 Tree 实例是什么意思?将树拆分为多个子树对性能更好吗?我试图重新创建此树遍历算法bfs-dfs-example 的功能,但我想用
DocumentA和/或DocumentB替换TreeNode。 -
关于这两种类型的文档,我还想澄清一件事。对不起,如果我没有很好地解释它,但 DocumentA 充当其他“子集合”(DocA)或“子项”(DocB)的一种“集合”(DocA)。而 DocumentB 只是作为一个项目,它可以单独存在(根节点)或者是“集合/子集合”(DocA)的子节点。所以树结构的一个例子可以是 DocA -> [DocB, DocB] OR DocA -> [DocA, DocA] -> [[DocB, DocB], [DocB, DocB]] 或 DocB
标签: typescript design-patterns types interface typescript-generics