“……解析为非模块实体并且无法使用此构造导入”是什么意思?


93

我有一些TypeScript文件:

MyClass.ts

class MyClass {
  constructor() {
  }
}
export = MyClass;

我的功能

function fn() { return 0; }
export = fn;

我的消费者

import * as MC from './MyClass';
import * as fn from './MyFunc';
fn();

这在尝试使用时给我错误 new

模块“ MyClass”解析为非模块实体,无法使用此构造导入。

当尝试打电话时 fn()

无法调用类型缺少调用签名的表达式。

是什么赋予了?


2
感谢您分享答案。我建议删除javascript作为主要标签并离开ecmascript-6,因为这里的主要标签是typescript。该问题错误地假定export =(TS功能)可以与配对import ... from,而应该与配对import =。与CJS / AMD相比,基本上是ES6模块的导入/导出。
Estus Flask

Answers:


156

为什么它不起作用

import * as MC from './MyClass';

这是ES6 / ES2015样式的import语法。确切的含义是“ 从中获取加载的模块名称空间对象./MyClass并在本地将其用作MC”。值得注意的是,“模块名称空间对象 ”仅由具有属性的普通对象组成。ES6模块对象不能作为函数或通过调用new

再说一遍:ES6模块名称空间对象不能作为函数或通过调用new

您在模块中import使用的事物* as X被定义为仅具有属性。在降级的CommonJS中,这可能不会得到完全遵守,但是TypeScript会告诉您该标准定义的行为是什么。

有什么用?

您需要使用CommonJS样式的导入语法才能使用此模块:

import MC = require('./MyClass');

如果同时控制两个模块,则可以使用export default

MyClass.ts

export default class MyClass {
  constructor() {
  }
}

我的消费者

import MC from './MyClass';

我为此感到难过;规则是愚蠢的。

使用ES6导入语法会很不错,但是现在我必须做这个import MC = require('./MyClass');事情吗?2013年就这样!瘸!但是悲伤是编程的正常部分。请跳至库伯勒·罗斯模型的第五阶段:验收。

这里的TypeScript告诉您这不起作用,因为它不起作用。有一些hacks(namespace向其添加声明MyClass是一种流行的伪装方式),它们现在可能在您特定的降级模块捆绑器(例如汇总)中起作用,但这是虚幻的。目前还没有任何ES6模块实现,但这并不是永远的。

想像一下您未来的自我,尝试在一个完整的本机ES6模块实现上运行,并通过尝试使用ES6语法执行ES6明确没有做的事情来发现自己已陷入重大故障。

我想利用我的非标准模块加载器

也许您有一个模块加载器,default当不存在导出器时会“有帮助”地创建导出。我的意思是,人们制定标准是有原因的,但是忽略标准有时很有趣,我们可以认为这是一件很酷的事情。

MyConsumer.ts更改为:

import A from './a';

并指定allowSyntheticDefaultImports命令行或tsconfig.json选项。

请注意,这allowSyntheticDefaultImports根本不会改变代码的运行时行为。它只是一个标志,告诉TypeScript当模块加载器default不存在时,它会创建导出。以前没有,它不会神奇地使您的代码在nodejs中工作。


commonjs样式是否不需要commonjs目标?当您定位到es6 / es2015时,有没有办法使此工作有效?
Steve Buzonas

您无法使其针对ES6,因为它在ES6中不起作用 ...
Ryan Cavanaugh

我是否理解正确,如果我以ES2015模块为目标,则无法引用具有以下内容的CommonJS模块export = MyClass?我唯一的选择是将模块设置为,commonjs并通过不使用现代ES继续使世界变得更糟?
米卡·佐尔图

6
2.7发行说明的--esModuleInterop,它表示“我们强烈建议将其应用于新项目和现有项目”。在我看来,这个答案(和FAQ条目/政策DefinitelyTyped这里的链接)应该进行修改,以反映新的立场。
亚历克·梅夫

1
真是太时髦了。
jmealy

25

TypeScript 2.7通过发出新的帮助器方法来引入支持:https : //www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#support-for-import-d-from-cjs-form- commonjs-with --- esmoduleinterop

因此,在tsconfig.json中添加以下两个设置:

{
    // Enable support for importing CommonJS modules targeting es6 modules
    "esModuleInterop": true,

    // When using above interop will get missing default export error from type check since
    // modules use "export =" instead of "export default", enable this to ignore errors.
    "allowSyntheticDefaultImports": true
}

现在您可以使用:

import MyClass from './MyClass';

除了使用之外,esModuleInteropresolveJsonModule还与其他使用建议一起使用allowSyntheticDefaultImports,它对我很有用。
Edgar Quintero

6

在这里加我的2美分,以防其他人遇到这个问题。

我无需修改tsconfig.json即可解决问题的方式(在某些项目中可能会出现问题),我只是禁用了oneline的规则。

import MC = require('./MyClass'); // tslint:disable-line


5

尝试在项目中包含npm反跳软件包时出现此错误。

当我尝试上面接受的解决方案时,我遇到了一个例外:

定位ECMAScript模块时,不能使用导入分配。考虑使用“ import * as ns from“ mod””,“ import {a} from“ mod””,“ import d from“ mod””或其他模块格式。

最终工作:

import debounce from 'debounce' 
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.