ECMAScript 6 - TypeScript 继承与 SystemJS 中的循环依赖
我在一个非常大的项目中使用 TypeScript,并使用 --module system(SystemJS)。SystemJS 支持循环依赖,大多数时候它都能正常工作。然而,当涉及到 TypeScript 的继承时,情况开始出现问题。
例如,如果 class A 依赖于 class B,并且 class B 继承 自 class A,那么如果 class A 先被加载:
- 它将暂停
类A的解析,并将尝试加载类B的依赖 class B会认为它的依赖项已解决,因为class A已经被触及。class B 的继承将无法解析,因为class A仍然未定义。
我在网上找到的大多数关于使用模块加载器处理循环依赖的“解决方案”要么是:
- 更改你的设计/将类合并到一个模块中
- CommonJS 和非 TypeScript 特定的解决方法
我觉得对循环设计有合理的理由,而且将类合并到巨大的文件中并不总是理想的,所以请考虑这些解决方法与我所提出的问题无关。
对实际问题有任何解决方案吗?
答案#1
改变你的设计是最可取的解决方案。一个类不应依赖于它的子类。如果你在工厂或其他地方使用它们,那是一个单独的问题,应该放在一个单独的类/函数/模块中。
对实际问题有任何解决方案吗?
正如你所说,问题仅在模块A首先被加载时发生。解决办法是防止这种情况,并编写一个额外的模块,在以正确顺序导入它们时充当A及其所有子类的代理。
答案#2
在这种情况下,我建议你通过创建一个独立的接口 I 来移除 A -> B 的依赖。A 和 B 都需要知道 I,并且 B 需要实现它。
在加载过程中,B 必须告诉 A 在哪里可以找到 I(由 B 实现)的构造函数或工厂。这将使你拥有这些依赖项:
A -> I
B -> I
B -> A
接口 I 可能看起来像这样:
interface I {
bFoo(): void;
}
export default I;
类 A 可能看起来像这样:
import I from "./i";
class A {
private static __ICtor : new() => I;
public static setIConstructor(ctor: new() => I) {
A.__ICtor = ctor;
}
private __atSomePoint() : I {
return new A.__ICtor();
}
}
export default A;
最后是 class B:
import I from "./i";
import A from "./a";
class B extends A implements I {
public bFoo() {}
}
A.setIConstructor(B);
依我看,这可以解决你的循环依赖问题,即使现在可能已经太晚了。
