A namespace-style import cannot be called or constructed, and will cause a failure at runtime
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...
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,
John.
Solution 1:
The error should only happen with esModuleInterop: true
. Maybe VSCode is ignoring your tsconfig.json
or another one with esModuleInterop: true
is used.
For a definitive fix set the compiler option esModuleInterop
to true
and use import express
instead of import * as express
.
The problem :
The ES6 specification defines the notion of "namespace object". A namespace object is namespaceObject
in this statement : import * as namespaceObject from 'a-module'
. The typeof
this object is object
, you are not supposed to be able to call it.
You were using import * as express
until now because express
is 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.
The solution :
Setting esModuleInterop
to true will make TypeScript wrap your import
calls 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.
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();).
Solution 2:
In my case I already had "esModuleInterop": true,
enabled is tsconfig.json
, I needed to convert:
import * as assert from "assert";
to:
import assert from "assert";