在TypeScript/ES6中,import *和import {specificName}有什么区别?

15

声明

declare module "MyModule" {

export function Foo() {...}
export function Bar() {...}

}

我只需要在某个地方使用Foo,我应该如何导入它?

import * as MyModule from "MyModule";

MyModule.Foo();
或者
import {Foo} from "MyModule";
Foo()

哪种方案比另一种更好?第一种方式导入所有导出是否会产生性能影响?

在发布问题之前我阅读了一些参考文献:

https://www.exratione.com/2015/12/es6-use-of-import-property-from-module-is-not-a-great-plan/


3
如果你只需要 Foo,为什么还要考虑使用 * as MyModule - Estus Flask
https://dev59.com/4XVC5IYBdhLWcg3w51ry - Sandeep Roy
2
@SandeepRoy 我在谈论 JavaScript,这里不会弄乱命名空间。 - Harshil Lodhi
1
@estus https://www.exratione.com/2015/12/es6-use-of-import-property-from-module-is-not-a-great-plan/@estus,https://www.exratione.com/2015/12/es6-use-of-import-property-from-module-is-not-a-great-plan/ - Harshil Lodhi
抱歉,在评论之前我应该先检查一下。 - Sandeep Roy
TypeScript和JS / Babel的导入方式不同。 TS:默认导入是import * from 'some-package'。要使用命名或默认导入(import {module_name} from 'some-package'或import default_module_name from 'some_package'),我们需要在tsconfig.json中启用esModuleInterop标志(esModuleInterop:true)。 - Pramod Mali
4个回答

7

仅导入代码中必需的部分,当然是良好的做法。假设有人编写了几千行代码并导入了所有东西,然后您试图分析它。您是否认为您可以轻松地知道哪些函数在您的代码中使用,哪些未被导入?显然这是可疑的和不良的做法

至于性能方面,我认为影响不大。


6

import {} from ... 语法使得对函数进行桩测试和间谍测试非常困难,通常需要使用额外的库,如 rewire.js。缺点是摇树优化效果不佳。我倾向于保持我的实用程序模块小,并且可能每个模块只包含2-3个函数。这样我就可以在我的模块中使用 import * as ... 语法,在可能的情况下使用 import {} ... 来引入第三方模块。从而最大程度地减少了对摇树优化的需求。


这篇博客文章提供了额外的信息,支持这个答案:https://www.exratione.com/2015/12/es6-use-of-import-property-from-module-is-not-a-great-plan/ - Asher Garland
1
我注意到在Jest中,从“import * as Foo from ...”和“import Foo from ...”导入的行为不同,后者可以进行存根而前者不能。很奇怪... - novomanish
1
如果你使用的工具不支持存根 import { foo } from './bar';,那就换更好的工具吧。 - airtonix
1
"需要注意的是,摇树优化并不总是有效。你能给我一些相关文档吗?在我使用两种导入方式时,摇树优化都能正常工作。我正在使用webpack,也许这是在过去几年中的新发展?" - Zevgon

3
如果你只需要使用Foo,那么最好只导入Foo。这样可以使你的代码更加清晰,因为通过查看导入的内容,你可以知道代码正在使用MyModule的哪些元素。
这不会影响性能,因为无论如何,你都必须读取/下载整个文件。
此外,当使用类似Rollup.js的打包工具时,选择哪个选项都不重要 - 即使你从MyModule导入所有内容,捆绑包也将仅包括你在代码中实际使用的内容。

1
我认为我们没有使用任何支持treeshaking的打包工具。 - Harshil Lodhi

0

如果有人仍在寻找答案,我已经分享了我的想法。

  • 假设您有一个JSON文件,并且希望将整个模块作为变量导入,则使用import *
  • 如果您有一个具有多个导出方法的模块(可以是第三方包),则应采用import {}方法。
  • 任何默认导出都应导入为“import 任何名称”。

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