Node.js + TypeScript: Unclear syntax with type script compiled code
If you are trying to use the default export of a non-ES6 module like Express.js, you need to use the legacy import syntax import express = require('express')
.
In ES6 modules, there is no default value export like the module.exports
of Node.js modules or the return
of AMD modules; the default export of an ES6 module is just the default
key. This is why, when you use an ES6 default import
as you are attempting to do, TypeScript generates JavaScript with an access to the default
property.
More information about this is available at New es6 syntax for importing commonjs / amd modules i.e. `import foo = require('foo')`.
The safest solution would be:
import express = require('express');
This transpiles to:
var express = require('express');
The official documentation for import require declarations can be found here.
I believe TypeScript expects an export named "default" to function as your code above, judging from the final paragraph here.
Side note: It looks like TypeScript's newest version ([email protected] at the time of writing) will throw a warning on a compile attempt which would attempt to use a missing default:
index.ts(1,8): error TS1192: Module '"express"' has no default export.
Side note 2: An example from Microsoft using the import * as express from 'express';
syntax can be found here. When targeting a module of commonjs
(as they are in this example), this will also transpile to var express = require('express');
.
If you have at least TypeScript 2.7 and are targeting CommonJS, you can use esModuleInterop, as well.
From the link:
To give users the same runtime behavior as Babel or Webpack, TypeScript provides a new --esModuleInterop flag when emitting to legacy module formats.
Under the new --esModuleInterop flag, these callable CommonJS modules must be imported as default imports like so:
import express from "express";
let app = express();
We strongly suggest that Node.js users leverage this flag with a module target of CommonJS for libraries like Express.js, which export a callable/constructable module.
If you still want to use the import
keyword then use it like:
import express from "express";
// If the above is not supported by your project environment then follow as below
import * as express from "express";
In file tsconfig.json
{
"compilerOptions": {
...
"module": "commonjs"
...
}
}
Thanks to Josh Dando.
I solved this by adding the following to tsconfig.json
:
{
"compilerOptions": {
...
"module": "commonjs",
"esModuleInterop": true,
...
}
}
The esModuleInterop flag is described as: "Emit __importStar and __importDefault helpers for runtime babel ecosystem compatibility and enable --allowSyntheticDefaultImports for typesystem compatibility."
https://www.typescriptlang.org/docs/handbook/compiler-options.html