94

我有一些 TypeScript 文件:

MyClass.ts

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

我的函数

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

我的消费者.ts

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

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

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

并且在尝试打电话时fn()

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

是什么赋予了?

4

4 回答 4

161

为什么它不起作用

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() {
  }
}

我的消费者.ts

import MC from './MyClass';

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

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

这里的 TypeScript 告诉你这是行不通的,因为它行不通。有一些技巧(添加namespace声明MyClass是一种流行的方式来假装它有效),它们今天可能在您特定的降级模块捆绑器(例如汇总)中工作,但这是虚幻的。目前还没有任何 ES6 模块实现,但这不会永远如此。

想象一下你未来的自己,试图在一个整洁的原生 ES6 模块实现上运行,并发现你已经通过尝试使用 ES6 语法来做一些 ES6 明确不做的事情,从而使自己面临重大失败。

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

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

将MyConsumer.ts更改为:

import A from './a';

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

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

于 2016-09-09T16:08:31.953 回答
25

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';
于 2018-08-09T03:21:37.417 回答
6

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

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

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

于 2017-10-16T04:03:39.223 回答
5

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

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

以 ECMAScript 模块为目标时,不能使用导入分配。考虑使用 'import * as ns from "mod"'、'import {a} from "mod"'、'import d from "mod"' 或其他模块格式。

这最终起作用了:

import debounce from 'debounce' 
于 2018-03-31T20:53:03.823 回答