我有一些 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
Module "MyClass" resolves to a non-module entity and cannot be imported using this construct.
当尝试调用 fn()
Cannot invoke an expression whose type lacks a call signature.
什么给了?
最佳答案
为什么不起作用
import * as MC from './MyClass';
这是 ES6/ES2015 风格的 import
语法。其确切含义是“获取从./MyClass
加载的模块命名空间对象,并在本地将其用作MC
”。值得注意的是,“模块命名空间对象”仅由具有属性的普通对象组成。 ES6 模块对象不能作为函数或使用 new
调用。
再说一遍:ES6 模块命名空间对象不能作为函数调用,也不能用new
调用。
您使用 * 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 告诉你这是行不通的,因为它行不通。有一些 hack(向 MyClass
添加 namespace
声明是一种假装有效的流行方式),它们今天可能在您的特定降级中起作用模块 bundler (例如汇总),但这是虚幻的。目前还没有任何 ES6 模块实现,但不会永远如此。
想象一下你 future 的自己,尝试在 neato 原生 ES6 模块实现上运行,并发现你已经为重大失败做好了准备 尝试使用 ES6 语法来做一些 ES6 明确不做的事情.
我想利用我的非标准模块加载器
也许你有一个模块加载器,当不存在时,它“有帮助地”创建 default
导出。我的意思是,人们制定标准是有原因的,但有时忽略标准很有趣,我们可以认为这是一件很酷的事情。
将 MyConsumer.ts 更改为:
import A from './a';
并指定 allowSyntheticDefaultImports
命令行或 tsconfig.json
选项。
请注意,allowSyntheticDefaultImports
根本不会更改代码的运行时行为。它只是一个标志,告诉 TypeScript 您的模块加载器在不存在时创建 default
导出。它不会神奇地让您的代码在 nodejs 中工作,而以前没有。
关于typescript - "... resolves to a non-module entity and cannot be imported using this construct"是什么意思?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39415661/