什么" ...解析为非模块实体,不能使用此构造导入"意思?

时间:2016-09-09 16:08:32

标签: typescript ecmascript-6 es6-modules

我有一些TypeScript文件:

MyClass.ts

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

MyFunc.ts

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

MyConsumer.ts

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

这在尝试使用new

时出现错误
  

模块" MyClass"解析为非模块实体,无法使用此结构导入。

并尝试拨打fn()

  

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

是什么给出了?

4 个答案:

答案 0 :(得分:147)

为什么它不起作用

import * as MC from './MyClass';

这是ES6 / ES2015风格的import语法。其确切含义是“从./MyClass加载模块名称空间对象,并在本地将其用作MC”。值得注意的是,“module namespace object ”仅包含具有属性的普通对象。无法将ES6模块对象作为函数或new调用。

再说一遍:无法将ES6模块命名空间对象作为函数或new调用。

import使用模块中* as X的内容被定义为仅具有属性。在下层的CommonJS中,这可能没有被完全尊重,但TypeScript告诉你标准定义的行为是什么。

有什么用?

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

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

如果您控制两个模块,则可以改为使用export default

MyClass.ts

export default class MyClass {
  constructor() {
  }
}

MyConsumer.ts

import MC from './MyClass';

我对此感到难过;规则很愚蠢。

使用ES6导入语法会很好,但现在我必须执行此操作import MC = require('./MyClass');?这是2013年!瘸!但悲伤是编程的一个正常部分。请跳到Kübler-Ross模型的第五阶段:接受。

这里的TypeScript告诉你这不起作用,因为它不起作用。有一些黑客(向namespace添加MyClass声明是一种流行的方式来假装这种方法),并且他们可能今天在你的特定下层模块捆绑器中工作(例如汇总) ,但这是虚幻的。野外还没有任何ES6模块实现,但这不会永远是真的。

想象未来的自我,尝试运行neato原生ES6模块实现,并发现你已经为尝试使用ES6语法执行ES6明确不做的事情而为重大失败做好准备< / em>的

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

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

MyConsumer.ts 更改为:

import A from './a';

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

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

答案 1 :(得分:20)

TypeScript 2.7通过发出新的帮助器方法来引入支持: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-7.html#support-for-import-d-from-cjs-form-commonjs-modules-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';

答案 2 :(得分:4)

在这里加上我的2美分,因为别人有这个问题。

我在不修改tsconfig.json的情况下处理这个问题的方式(在某些项目中可能会有问题),我只是简单地禁用了oneline规则。

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

答案 3 :(得分:4)

尝试在我的项目中包含npm debounce包时出现此错误。

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

  

定位ECMAScript模块时无法使用导入分配。   考虑使用&#39; import *作为来自&#34; mod&#34;&#39;,&#39;导入{a}来自&#34; mod&#34;&#39;,   &#39;从&#34; mod&#34;&#39;或其他模块格式导入d。

这最终起作用了:

sed -i 's|1006\.2|Irradiance (W/m^2) &|g' file1.1