Typescript:导出命名空间中的所有函数

zer*_*oin 12 typescript

让我说我有一个打字稿文件Utils与一堆导出函数:

export function utilOne(){}
export function utilTwo(){}
Run Code Online (Sandbox Code Playgroud)

我将index.d.ts文件添加到此文件夹中,我从Utils文件中导出*:

export * from './Utils';
Run Code Online (Sandbox Code Playgroud)

在我的其他类中,我想通过utils命名空间访问函数utilOne和utilTwo,如:

utils.utilOne();
Run Code Online (Sandbox Code Playgroud)

我知道我可以像这样导入它:

import * as utils from "./Utils";
Run Code Online (Sandbox Code Playgroud)

但是,由于我将使用utils很多,我希望能够在命名空间中导出utils,例如:

export {* as utils} from './Utils';   // this doesn't work
Run Code Online (Sandbox Code Playgroud)

然后使用:

import * from "./Utils";
Run Code Online (Sandbox Code Playgroud)

但是导出{*as utils}不起作用.我可以把Utils的所有功能都放到模块"utils"中并导出它,但我不确定这是不是一个好习惯.有没有正确的方法来做到这一点?

Ser*_*rov 14

TC39/ecma 262起,您可能需要的功能已合并。\n所以现在您可以像这样导出模块本身:

\n
// module.ts\n\nexport interface Foo{\n    bar: string;\n}\n\nexport function A(){\n  // implementation\n}\n\nexport function B(){\n  // implementation\n}\n\nexport * as MyModule from \'./module\';\n
Run Code Online (Sandbox Code Playgroud)\n

然后像使用包含自己上下文的模块一样使用它:

\n
import { MyModule } from \'./module\';\n\ntype MyType = MyModule.Foo;\n\nMyModule.A();\nMyModule.B();\n
Run Code Online (Sandbox Code Playgroud)\n

在我看来,如果你使用它,这取决于 TS 版本和 Webpack。

\n
    \n
  • Webpack 5和 TS v4.1.2 运行良好。
  • \n
  • Vite js - 也运行得很好。\n还没有检查树摇动,但看起来它应该运行得很好。
  • \n
\n

更新:

\n

在上面的情况下,一切都很好,但是,聚合模块会导出自身,如果您尝试用它来检查这一点madge --circular [directory],则会显示存在循环依赖关系。

\n

因此,为了避免这种情况,我们可以遵循Mmdn web 文档并添加中间文件,例如barrel.ts

\n
\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 src\n\xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 main.js\n\xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 myModule\n\xe2\x94\x82   \xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 functionA.js\n\xe2\x94\x82   \xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 functionB.js\n\xe2\x94\x82   \xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 barrel.js\n\xe2\x94\x82   \xe2\x94\x82   \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 index.js\n\n// -- myModule/functionA.js --\nexport function A(){\n  return \'this is module A\' \n}\n  \n// -- myModule/functionB.js --\nexport function B(){\n  return \'this is module B\' \n}\n\n// -- myModule/barrel.js --\nexport * from "./functionA.js";\nexport * from "./functionB.js";\n\n// -- myModule/index.js\nexport * as MyModule from \'./barrel.js\';\n\n// -- main.js --\nimport { MyModule } from "./myModule";\nconsole.log(MyModule.A); // this is module A\nconsole.log(MyModule.B); // this is module B\n
Run Code Online (Sandbox Code Playgroud)\n


bas*_*rat 9

进口于

不会.即使在支持它们的语言中,全球进口也被视为不良做法.(例如python 为什么"import*"不好?)

JavaScript/TypeScript不支持它.毕竟它非常有用,可以看到foo.bar并知道条形图来自foo而不是bar不知道哪里有条形图(没有克隆和分析整个项目).

  • 我认为除了最后一行之外,这是一个很好的问题,并且值得回答,尽管要求采取不好的做法。他们可以很容易地要求能够执行 `import { utils } from './Utils'` 我有一个由一堆文件组成的库。我希望库中的导出按文件命名,而不是全部塞到单个模块范围的命名空间中。我相信这和OP想要的一样。 (3认同)
  • 这根本没有回答问题,甚至脱离了主题。OP 正是要求对他的模块进行类似 obj 的访问,并询问 glob 导出而不是导入。 (2认同)

Zac*_*sky 5

除了注意事项之外,根据您的项目,可以利用一层间接来完成此导出。

./utils/internal/utils.ts

export function utilOne(){}
export function utilTwo(){}
Run Code Online (Sandbox Code Playgroud)

./utils/utils.ts

import * as utils from './internal/utils';
export utils;
Run Code Online (Sandbox Code Playgroud)

./test.ts

import { utils } from './utils/utils';

utils.utilOne();
Run Code Online (Sandbox Code Playgroud)

注意事项:

如前所述,这是一种有问题的做法,并且对命名空间的渴望可能表明存在代码味道。它还可能会对您的库和由此产生的项目的树可摇动性产生负面影响。

注意:这个结构受到 RxJS 的启发。