如何在TypeScript中从一个目录导入所有模块?

76
在TypeScript中handbook介绍了几种模块导入的技巧:
  • 从一个模块中导入单个导出项:import { ZipCodeValidator } from "./ZipCodeValidator";
  • 从一个模块中导入单个导出项并将其重命名:import { ZipCodeValidator as ZCV } from "./ZipCodeValidator";
  • 导入整个模块:import * as validator from "./ZipCodeValidator";

我认为还有一种选择,但我无处找到它。是否有可能从给定目录导入所有模块?

我猜语法应该是这样的:import * from "./Converters"


4个回答

101

不,这是不可能的。大多数人所做的是创建一个index.js文件,该文件重新导出同一目录中的所有文件。

示例:

这种方法并不能真正地隐藏被导入文件的实际位置,但它可以使项目结构更加清晰,并且方便进行整体的导入和导出操作。

my-module/
  a.ts
  b.ts
  index.ts

a.ts

export default function hello() {
  console.log("hello");
}

b.ts

export default function world() {
  console.log("world");
}

index.ts

export { default as A } from "./a";
export { default as B } from "./b";

您可以使用*字符来重新导出模块的每个导出项,只需一行代码即可。请注意,如果已经导出了同名成员,TypeScript会报错(感谢 @haysclark 提供的提示)。

export * from "./somePath";
索引名称可以被省略(与 JavaScript 中一样):
import * as whatever from "./my-module";

console.log(whatever);
// Logs: { A: [Function: hello], B: [Function: world] }

1
如果所有添加的文件都在index.ts中导出,如何编写测试用例? 例如,如果d.ts未添加到index.ts中,如何以编程方式避免这种情况? - Raghavendra
1
这不是我要问的。 以上的答案为例,我想编写测试来检查是否已将所有a.ts、b.ts添加到index.ts文件中? - Raghavendra
1
@marvinhagemeister 可能值得将export * from "./somePath";添加到您的答案中。 :D - haysclark
值得注意的是,根据您的构建配置,使用索引文件可能会显著增加构建时间。特别是如果您只从所选文件夹中使用了几个项目,这一点尤其明显。 - Robert
请不要这样做。它会对智能感知造成严重影响(CMD+单击会导致只显示一堆无用的导出文件)。我经常看到这种模式,但从未喜欢过它,为什么不直接从文件所在位置导入呢?这样更容易理解,并且可以立即清楚地看到代码库在任何给定文件中是如何组织的。 - fullStackChris
显示剩余4条评论

22

我不确定这是否适用于生产代码,但我使用以下方法在目录中导入测试代码

import glob from 'glob'

new Promise((resolve, reject) => {
  glob(__dirname + '/**/*.ts', function (err, res) {
    if (err) {
      reject(err)
    } else {
      Promise.all(
        res.map(file => {
          return import(file.replace(__dirname, '.').replace('.ts', ''))
        })
      ).then(modules => {
        resolve(modules)
      })
    }
  })
}).then(modules => {
  // do stuff
})

1
应该被接受为答案,我个人认为。谢谢这个。 - ALFmachine

5
这是@tom-howard使用ES2022语法的答案。
import glob from 'glob';

let modules;

try {
  const res = await glob(__dirname + '/**/*.ts');
  modules = Promise.all(res.map((file) => (
    import(file.replace(__dirname, '.').replace('.ts', ''))
  )));
} catch (err) {
  // handle `err`
}

// use `modules`

3

使用一个 index file 导入文件夹中的所有内容,这在我看来更易读一些:

文件夹结构:

|-app.ts
|-layout
    |-navbar.ts
    |-sidebar.ts
    |-index.ts

layout/navbar.ts

export default () => ({ nav: 'bar' })

layout/sidebar.ts

export default () => ({ side: 'bar' })

layout/index.ts

import navbar from './navbar'
import sidebar from './sidebar'

export {navbar, sidebar}

app.ts

import * as layout from './layout'

console.log(layout.navbar()) // { nav: 'bar' }
console.log(layout.sidebar()) // { side: 'bar' }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接