typescript 无法调用或构造命名空间样式的导入,并且会导致运行时失败

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/49256040/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 05:16:47  来源:igfitidea点击:

A namespace-style import cannot be called or constructed, and will cause a failure at runtime

typescriptexpresstypescript-typings

提问by John Gorter

Strange stuff happening here, with TypeScript 2.7.2, in VSCode version 1.21 with @types/express and the code that follows, in some cases VSCode throws errors stating that "A namespace-style import cannot be called or constructed, and will cause a failure at runtime.". However on other machines with similar setups and similar tsconfig.json files the code just works.. What is happening here:

这里发生了一些奇怪的事情,在 TypeScript 2.7.2 中,在 VSCode 1.21 版中带有 @types/express 和随后的代码,在某些情况下,VSCode 会抛出错误,指出“无法调用或构造命名空间样式的导入,并且会导致运行时失败。”。然而,在其他具有类似设置和类似 tsconfig.json 文件的机器上,代码可以正常工作。这里发生了什么:

import { Bank } from './Bank';
import * as Express from 'express';  <== errors here..

let app: Express.Express;
this.app = Express();                <== and here

Why is this happening?

为什么会这样?

TIA,

TIA,

John.

约翰。

回答by fathy

The error should only happen with esModuleInterop: true. Maybe VSCode is ignoring your tsconfig.jsonor another one with esModuleInterop: trueis used.

错误应该只发生在esModuleInterop: true. 也许 VSCode 忽略了你的tsconfig.json或另一个esModuleInterop: true使用的。

For a definitive fix set the compiler option esModuleInteropto trueand use import expressinstead of import * as express.

对于最终解决设定的编译器选项esModuleInterop,以true和使用import express代替import * as express

The problem:

问题

The ES6 specification defines the notion of "namespace object". A namespace object is namespaceObjectin this statement : import * as namespaceObject from 'a-module'. The typeofthis object is object, you are not supposed to be able to call it.

ES6 规范定义了“命名空间对象”的概念。Namespace对象是namespaceObject在此声明:import * as namespaceObject from 'a-module'。在typeof此目标是object,你是不是应该能够调用它。

You were using import * as expressuntil now because expressis a CommonJS module, for Node.js, it is exported using module.exports. However it is illegal in the ES6 spec, and TypeScript now warns you.

您一直使用import * as express到现在是因为它express是一个 CommonJS 模块,对于 Node.js,它是使用module.exports. 然而,它在 ES6 规范中是非法的,TypeScript 现在会警告你。

The solution:

解决办法

Setting esModuleInteropto true will make TypeScript wrap your importcalls to check if the module is an ES6 module or a CommonJS. If it's a CommonJS module and you are using import default from 'module'TypeScript will find out and return the correct CommonJS module.

设置esModuleInterop为 true 将使 TypeScript 包装您的import调用以检查模块是 ES6 模块还是 CommonJS。如果它是一个 CommonJS 模块,并且你正在使用import default from 'module'TypeScript 会找出并返回正确的 CommonJS 模块。

From the TypeScript release note:

打字稿发行说明

Note: The new behavior is added under a flag to avoid unwarranted breaks to existing code bases. We highly recommend applying it both to new and existing projects. For existing projects, namespace imports (import * as express from "express"; express();) will need to be converted to default imports (import express from "express"; express();).

注意:新行为添加在一个标志下,以避免对现有代码库造成不必要的破坏。我们强烈建议将其应用于新项目和现有项目。对于现有项目,命名空间导入(import * as express from "express"; express();)需要转换为默认导入(import express from "express"; express();)。