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

What does "... resolves to a non-module entity and cannot be imported using this construct" mean?

我有一些 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-style import 语法。这句话的确切含义是"Take the module namespace object loaded from ./MyClass and use it locally as 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 告诉你这是行不通的,因为它行不通。有 hack(向 MyClass 添加 namespace 声明是一种假装有效的流行方式),它们 可能 今天在您特定的降级模块捆绑器中工作(例如汇总),但这是虚幻的。目前还没有任何 ES6 模块实现,但不会永远如此。

想象一下你未来的自己,尝试 运行 在 neato 原生 ES6 模块实现上发现你已经通过 尝试使用 ES6 语法来做某事而为重大失败做好准备ES6 明确不做 .

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

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

MyConsumer.ts改为:

import A from './a';

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

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

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

我在不修改 tsconfig.json 的情况下解决问题的方法(这在某些项目中可能会出现问题),我只是简单地禁用了 oneline 的规则。

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

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

当我尝试上面接受的解决方案时出现异常:

Import assignment cannot be used when targeting ECMAScript modules. Consider using 'import * as ns from "mod"', 'import {a} from "mod"', 'import d from "mod"', or another module format instead.

这最终成功了:

import debounce from 'debounce' 

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';