typescript - En import i namnrymdsstil kan inte anropas eller konstrueras, och kommer att orsaka ett fel vid körning


Med TypeScript 2.7.2, i VSCode version 1.21 med @types/express och koden som följer, i vissa fall visar VSCode fel som säger att

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

Men på andra datorer med liknande uppsättningar och liknande tsconfig.json-filer fungerar koden bara. Vad händer här...

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

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

Varför händer detta?

TIA,

John.

Svar #1

Felet bör bara inträffa med esModuleInterop: true. Kanske ignorerar VSCode din tsconfig.json eller så används en annan med esModuleInterop: true.

För en definitiv lösning, ställ in kompilatoralternativet esModuleInterop till true och använd import express istället för import * as express.

Problemet :

Specifikationen för ES6 definierar begreppet "namespaceobjekt". Ett namespaceobjekt är namespaceObject i detta uttalande: import * as namespaceObject from 'a-module'. typeof på detta objekt är object, du ska inte kunna anropa det.

Du använde import * as express hittills eftersom express är en CommonJS-modul, för Node.js exporteras den med module.exports. Men det är olagligt enligt ES6-specifikationen, och TypeScript varnar dig nu.

Lösningen :

Att sätta esModuleInterop till true kommer göra att TypeScript kapslar in dina import-anrop för att kontrollera om modulen är en ES6-modul eller en CommonJS. Om det är en CommonJS-modul och du använder import default from 'module' kommer TypeScript att ta reda på det och returnera rätt CommonJS-modul.

Från TypeScript-utgivningsanteckningen:

Observera: Det nya beteendet har lagts till under en flagga för att undvika oönskade brytningar i befintliga kodbaser. Vi rekommenderar starkt att det appliceras både på nya och befintliga projekt. För befintliga projekt måste namespace-importer (import * as express from "express"; express();) konverteras till standardimporter (import express from "express"; express();).

Svar #2

I mitt fall hade jag redan "esModuleInterop": true aktiverat i tsconfig.json. Jag behövde konvertera:

import * as assert from "assert";

till :

import assert from "assert";

Relaterade artiklar