【问题标题】:TypeScript inheritance and circular dependencies in SystemJSSystemJS 中的 TypeScript 继承和循环依赖
【发布时间】:2016-05-18 17:43:42
【问题描述】:

我在一个非常大的项目中使用带有--module system (SystemJS) 的 TypeScript。 SystemJS 支持循环依赖,并且大部分时间都可以正常工作。然而,当涉及到 TypeScript 继承时,事情就开始崩溃了。

例如,如果class A 依赖于class B,并且class B 继承来自class A,那么如果首先加载class A

  1. 它将暂停class A's 解析并尝试加载class B 依赖项
  2. class B 会认为它的依赖关系已解决,因为 class A 已被触及。
  3. class B's 继承将无法解析,因为 class A 仍未定义。

我可以在网上找到的大多数与模块加载器循环依赖的“解决方案”是:

  • 更改您的设计/将类合并到一个模块中
  • CommonJS 和非 TypeScript 特定的解决方法

我觉得循环设计有充分的理由,将类组合成巨型文件并不总是可取的,因此请考虑这些变通方法与我所问的问题无关。

对于实际问题有什么解决方案吗?

【问题讨论】:

    标签: typescript ecmascript-6 circular-dependency systemjs es6-module-loader


    【解决方案1】:

    更改您的设计是最有利的解决方案。一个类不应该依赖于它的子类。如果您在工厂左右使用它们,那是一个单独的问题,应该放在单独的类/函数/模块中。

    有没有解决实际问题的办法?

    正如您所说,仅在首先加载模块 A 时才会出现问题。解决方案是防止这种情况发生,并编写一个额外的模块作为 A 及其所有子类的代理,同时以正确的顺序导入它们。

    【讨论】:

      【解决方案2】:

      在这种情况下,我建议您通过创建一个单独的接口I 来删除A -> B 的依赖关系。 AB都需要知道IB需要实现。

      在加载过程中B 必须告诉A 在哪里可以找到I 的构造函数或工厂(由B 实现)。这将为您留下这些依赖项:

      A -> I
      B -> I
      B -> A
      

      接口I 可能如下所示:

      interface I {
        bFoo(): void;
      }
      
      export default I;
      

      Class 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);
      

      恕我直言,这将解决您的循环依赖,即使现在为时已晚。

      【讨论】:

        【解决方案3】:

        这里有一个巧妙的方法可以通过使用 Babel 转换插件来解决这个问题:https://github.com/zertosh/babel-plugin-transform-inline-imports-commonjs

        它的作用是将文件开头的模块导入转换为内联要求,仅在使用其他模块之前实际导入/需要它们。

        在大多数情况下,这会自动解决问题,因为当任何使用类的代码实际运行时,模块都已完成导出。


        请注意,默认情况下,上面的插件适用于您项目中的所有导入,将它们全部转换为内联需求。然而,一个更严重的问题是,我找不到一种内置方法来使它与相对路径导入/要求一起工作。

        我在我的项目分支中修复了这两个问题:https://github.com/Venryx/babel-plugin-transform-inline-imports-commonjs

        我对这些更改提出了拉取请求,但它正在等待审核 atm。

        【讨论】:

          猜你喜欢
          • 2016-02-27
          • 1970-01-01
          • 2014-08-28
          • 2022-01-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多