用于导入 commonjs / amd module的新 es6 语法,即`import foo = require('foo')`

IT技术 javascript typescript ecmascript-6
2021-02-10 16:22:12

以前我可以这样做:

import foo = require('foo');

但是现在 TypeScript (1.5) 支持 es6 module语法,在 ES6 module语法中实现相同的正确方法是什么。

6个回答

正确的方法是继续使用旧的导入语法。新的导入语法仅适用于 ES module,旧的导入语法适用于 ES6 之前的module。两者是不同的,故意如此。import * as foo from 'foo'导入module 'foo' 的所有属性,它不会将默认值导入为foo.

来自该功能的设计师

  • 导出默认声明始终声明一个名为 default 的导出成员,并且始终作为对exports.default 的赋值发出。换句话说,export default始终具有 ES module语义。为了与 Babel 兼容,__esModule当module具有默认导出时,我们可以选择发出一个标记,但我们实际上不会将该标记用于任何事情。
  • 一个export =声明,它替换一个不同的实体来代替module本身,总是作为对 的赋值发出module.exports在使用export =. 这是现有的 TypeScript 行为。
  • 使用一个moduleexport =导出另一module(是内部或外部module)可以使用新ES6构建体被导入。特别是,方便的解构导入可以与此类module一起使用。export =用于导出另一个module的模式在 .d.ts 文件中很常见,这些文件提供内部module的 CommonJS/AMD 视图(例如 angular.d.ts)。
  • module使用export =到位本身必须使用现有的导入module的非实体module输出import x = require("foo")的语法是今天的情况。

2016 年更新: TypeScript 编译器在某些时候开始允许import * as foo from 'legacy-module-foo'在某些情况下获取旧module的默认导入。这违反了 ES6 规范(第15.2.1.16 节“值“*”表示导入请求是针对目标module的命名空间对象。”)。

当您以这种方式导入的遗留module更新为 ES6 module时,这些module的“默认”导入将停止工作(因为* as foo导入应该是导入命名空间对象),如果您不知道这样做,这可能会非常混乱这是一个 TypeScript/SystemJS hack。未来 TypeScript 对 ES 规范的重新调整也有可能导致它们崩溃。

因此,您可能更愿意继续使用上述的遗留导入语法来加载遗留module,以避免让您自己和其他开发人员对 ES6 命名空间导入的工作方式感到困惑,并避免混淆破坏性更改。

谢谢。我已经要求澄清:github.com/Microsoft/TypeScript/issues/...
2021-03-12 16:22:12
@CSnover“如果你想使用遗留module,你不能以 ES6 环境为目标” - 现在这真的很荒谬......谁不需要使用第三方遗留module?!Babel 以更理智的方式处理它。
2021-03-20 16:22:12
这变得更加混乱,因为对于从 ES6/Babel 编译的 cjs module,新import * as <name> from <'module'>语法仍然有效
2021-03-21 16:22:12
现在已经过时了,对吗?如果我针对 ES6,它 TS 告诉我这import x = require('foo')是不允许的
2021-03-27 16:22:12
不,它并没有过时。import不违反 EcmaScript 规范的情况下,无法在真正的 ES6 module中导入带有 ES6 的非 ES6 module的默认值如果您想使用遗留module,则不能以 ES6 环境为目标,因为import在这种情况下TypeScript 编译器会按原样发出语句,并且 ES 规范没有任何针对具有默认导出的 CJS/AMD module的规定。
2021-04-06 16:22:12

ES6 module语法对应的语法是:

import * as foo from 'foo';

基本上将foomodule中的所有内容导入到名为foo.

我必须警告不要用 import * as name from 替换 import name = require 。如果module是 ES6 之前的module,你会遇到问题。如果在需要module时启动了一些初始化代码,则可能无法使用最新的 Typescript 运行。升级到 Typescript 2.0.3 后,我也遇到了 typescript 警告,并且不得不将 import * 更改为 import require 版本。
2021-03-16 16:22:12
@ user3717718你可以发布这个东西这里的后续问题:stackoverflow.com/questions/54446403/...那时候我想过那个。听起来像 import blah = require 是最好的,但我担心使用非标准 JS 的东西
2021-04-01 16:22:12
与此相关的导出语法是什么?resolves to a non-module entity and cannot be imported using this construct当我尝试export {Output}; 在旧文件的底部进行替换时,我得到了export = Output
2021-04-09 16:22:12

TypeScript 2.7 开始,有一个新esModuleInterop标志可用于启用 CommonJS/AMD/UMD 的默认导入。通过true在您的 中将该标志设置为tsconfig.json,这应该可以按预期工作:

import foo from 'foo';

ES6 module实际上是具有新语法的 TypeScript 外部module:ES6 module是单独加载的源文件,可能会导入其他module并提供许多外部可访问的导出。ES6 module具有几个新的导出和导入声明。建议更新 TypeScript 库和应用程序以使用新语法,但这不是必需的。

来源

据我了解,这意味着鼓励您将自己的 TypeScript module迁移到新语法,但继续import foo = require('foo')用于导入实际的 AMD/CommonJS module。

该声明有点误导,因为它来自 Microsoft。ES6 与 Typescript 无关。Typescript 与 ES6 的相似之处在于它也有一个预标准module系统(就像 Angular 1 有一个预标准module系统一样)。既然有了正式的标准,那么执着于前标准的 TS module是很鲁莽的。
2021-03-17 16:22:12

导入所有,

const foo = require("foo");

如果它是一个文件,这将从包“foo”中导入所有实例

const foo = require("./foo");

所以你可以通过调用访问每个实例, foo.InstanceName

如果要导入特定实例,

import MyInstance from "foo";

所以这将从“foo”导入特定实例(Myinstance),您仍然可以使用上述方法导入所有实例,

import * as ReferenceName from "foo";

它相当于,

const ReferenceName = require("foo");