“...解析为非模块实体并且不能使用此构造导入”意思? [英] What does "... resolves to a non-module entity and cannot be imported using this construct" mean?

查看:3129
本文介绍了“...解析为非模块实体并且不能使用此构造导入”意思?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些TypeScript文件:



MyClass.ts

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

MyFunc.ts

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

MyConsumer.ts



'pre> import *作为MC从'./MyClass';
import * as fn from'./MyFunc';
fn();

尝试使用新的


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


当尝试调用 fn()


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


什么给了?

解决方案

为什么不工作



 从* ./MyClass导入*作为MC。 

这是ES6 / ES2015风格的导入句法。其确切含义是从 ./ MyClass 加载的模块命名空间对象,并在本地使用它作为 MC 。值得注意的是,模块命名空间对象仅由具有属性的普通对象组成。 ES6模块对象不能作为一个函数或新调用



再说一遍: ES6模块命名空间对象不能作为函数或新调用



导入使用 *作为X 从模块定义为仅具有属性。在下来的CommonJS中,这可能不会被完全尊重,但是TypeScript告诉你标准定义的行为是什么。



什么工作?



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

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

如果您同时控制这两个模块,可以使用 export default 代替:



MyClass.ts

  export default class MyClass {
constructor(){
}
}

MyConsumer.ts

 从'./MyClass'导入MC; 



我很伤心关于这个;规则是笨拙的。



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



此处的TypeScript告诉您这不工作,因为它不起作用。有一些hacks(添加一个命名空间声明到 MyClass 是一种流行的方式来假装这个工作),而他们>可能今天在您的特定的低级模块捆绑器(例如汇总)中工作,但这是虚幻的。在野外没有任何ES6模块实现,但永远不会是真正的。



展示未来的自我,试图运行在一个neato本机ES6模块实现,并发现您已设置自己的主要故障,通过尝试使用ES6语法来执行ES6显式不执行的操作。



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



也许你有一个模块加载程序有帮助创建 default 当不存在时导出。我的意思是,人们为了理由而制定标准,但忽略标准是有趣的,我们可以认为这是一件很酷的事情。



更改 MyConsumer.ts 到:

 从'./a'导入A 

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



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


I have some TypeScript files:

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();

This gives me errors when trying to use new

Module "MyClass" resolves to a non-module entity and cannot be imported using this construct.

and when trying to call fn()

Cannot invoke an expression whose type lacks a call signature.

What gives?

解决方案

Why it doesn't work

import * as MC from './MyClass';

This is ES6/ES2015-style import syntax. The exact meaning of this is "Take the module namespace object loaded from ./MyClass and use it locally as MC". Notably, the "module namespace object" consists only of a plain object with properties. An ES6 module object cannot be invoked as a function or with new.

To say it again: An ES6 module namespace object cannot be invoked as a function or with new.

The thing you import using * as X from a module is defined to only have properties. In downleveled CommonJS this might not be fully respected, but TypeScript is telling you what the behavior defined by the standard is.

What does work?

You'll need to use the CommonJS-style import syntax to use this module:

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

If you control both modules, you can use export default instead:

MyClass.ts

export default class MyClass {
  constructor() {
  }
}

MyConsumer.ts

import MC from './MyClass';

I'm Sad About This; Rules are Dumb.

It would have been nice to use ES6 import syntax, but now I have to do this import MC = require('./MyClass'); thing? It's so 2013! Lame! But grief is a normal part of programming. Please jump to stage five in the Kübler-Ross model: Acceptance.

TypeScript here is telling you this doesn't work, because it doesn't work. There are hacks (adding a namespace declaration to MyClass is a popular way to pretend this works), and they might work today in your particular downleveling module bundler (e.g. rollup), but this is illusory. There aren't any ES6 module implementations in the wild yet, but that won't be true forever.

Picture your future self, trying to run on a neato native ES6 module implementation and finding that you've set yourself up for major failure by trying to use ES6 syntax to do something that ES6 explicitly doesn't do.

I want to take advantage of my non-standard module loader

Maybe you have a module loader that "helpfully" creates default exports when none exist. I mean, people make standards for a reason, but ignoring standards is fun sometimes and we can think that's a cool thing to do.

Change MyConsumer.ts to:

import A from './a';

And specify the allowSyntheticDefaultImports command-line or tsconfig.json option.

Note that allowSyntheticDefaultImports doesn't change the runtime behavior of your code at all. It's just a flag that tells TypeScript that your module loader creates default exports when none exist. It won't magically make your code work in nodejs when it didn't before.

这篇关于“...解析为非模块实体并且不能使用此构造导入”意思?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆