【问题标题】:How to best emulate namespaces in Typescript?如何在 Typescript 中最好地模拟命名空间?
【发布时间】:2021-07-18 14:01:26
【问题描述】:

我意识到命名空间在 ES6 中基本上已被弃用,并且在 Visual Code 中效果不佳。

但我仍然想使用它们。为什么?因为我的代码分布在多个要分组的文件中,而不会在它们之间创建依赖关系。

这是用例。我在不同的文件中有两个不同的商店:

   // fooStore.ts
   class FooStore { numFoos = 0; }

   export const fooStore = new FooStore();

   // barStore.ts
   class BarStore { numBars = 0; }

   export const barStore = new BarStore();

为了便于发现,我想将这些商店组合在一起,以便开发人员可以参考stores.fooStorestores.barStore

一种解决方案是导出一个包含两者的对象,如下所示:

export const stores = {
  fooStore,
  barStore
};

这可行,但它有一个很大的缺点。如果任何代码引用了stores.,那么所有引用的存储及其所有依赖项都会被拉入。为什么这是个问题?因为我在一个代码库中工作,该代码库是 AngularJS 类(遗留代码)和 React/MobX 代码(我们要移植到的)的组合,并且我们的一些商店使用 AngularJS。当我编写单元测试或 Storybook 故事时,我不想为我什至不感兴趣的商店设置所有必要的依赖项。

我真正想做的是这样的事情,但我知道不建议这样做。那我应该怎么做呢?

 // fooStore.ts
 class FooStore { numFoos = 0; }

 namespace Stores {
   export const fooStore = new FooStore();
}

【问题讨论】:

    标签: typescript ecmascript-6 es6-modules javascript-namespaces


    【解决方案1】:

    我可以想到 2 种平庸的方法来实现这一点,但它们都有缺点:

    1。使用惰性getter 在存储被访问时加载它。

    const stores = {
      get fooStore () {
        return require("path/to/fooStore");
      }
    }
    

    像这样的动态需求可能会在您的构建步骤中表现不佳。

    2。让商店在初始化时向 Store of Stores 注册自己:

    export const stores = {};
    export class Store {
      constructor(storeName) {
        stores[storeName] = this;
      }
    }
    

    这确实需要加载 FooStore 文件才能在 Store of Stores 上使用。

    【讨论】:

      【解决方案2】:

      一种解决方案是导出包含它们的对象

      是的,这会导致问题,因为它需要引入依赖项,才能将存储实例放入您的对象中。相反,为此使用具有命名导出的模块:

      // stores/index.ts
      export { fooStore } from './fooStore.ts';
      export { barStore } from './barStore.ts';
      

      然后您可以使用 命名空间导入 对它们进行分组:

      import * as stores from 'stores';
      
      console.log(stores.fooStore.numFoos);
      

      这仍然允许摇树 - 上面的模块不引用stores.barStore,因此不需要加载该模块(即使它被声明为依赖项)。

      【讨论】:

      • 我认为这正是我想要的。还有一个问题:你知道嵌套命名空间的方法吗?即stores.app.fooStore等?
      • 理论上你可以 export { stores }; 作为命名空间导入后,并以此构建嵌套对象,但我不确定捆绑器/加载器对此支持树抖动的程度如何。
      猜你喜欢
      • 2017-01-08
      • 1970-01-01
      • 2018-10-31
      • 1970-01-01
      • 2011-10-04
      • 2017-07-25
      • 1970-01-01
      • 2018-07-24
      • 2021-01-22
      相关资源
      最近更新 更多