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

TypescriptExpressTypescript Typings

Typescript Problem Overview


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.

Typescript Solutions


Solution 1 - Typescript

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 - Typescript

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";

Solution 3 - Typescript

How about this:

import express = require('express');

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJohn GorterView Question on Stackoverflow
Solution 1 - TypescriptFathyView Answer on Stackoverflow
Solution 2 - TypescriptmikemaccanaView Answer on Stackoverflow
Solution 3 - TypescriptyohanesView Answer on Stackoverflow