microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
100.4k stars 12.41k forks source link

Can't import Express 4 when targeting ES6 #13340

Closed realyze closed 7 years ago

realyze commented 7 years ago

TypeScript Version: 2.1.4

Issue Using @types/express: 4.0.34.

import express from "express"; fails to compile with Module '"/Users/realyze/code/myproj/node_modules/@types/express/index"' has no default export but the app works.

import * as express from "express"; compiles fine but the app the crashes on const app = express() with TypeError: express is not a function

The latter works & compiles when I'm targeting ES5.

I believe this repo showcases the problem: https://github.com/mhegazy/express-es6-ts-example

realyze commented 7 years ago

Here's my tsconfig.json:

{
    "compilerOptions": {
        "target": "es6",
        "noImplicitAny": false,
        "sourceMap": true,
        "jsx": "preserve",
        "experimentalDecorators": true,
        "moduleResolution": "node"
    },
    "lib": ["DOM", "es6"],
    "exclude": [
        "node_modules",
        ".meteor"
    ]
}
HerringtonDarkholme commented 7 years ago

Do you use any other transpiler or module resolver? Like Babel or webpack. As far as I can tell, under es6 target, TypeScript will emit native import which node does not support. You will encounter a syntax error before TypeError.

aluanhaddad commented 7 years ago

@realyze If your app works at runtime with the default import syntax, you are using a loader or bundler that does a mapping from module.exports to exports.default. In that case, simply add "allowSyntheticDefaultImports": true to "compilerOptions".

@HerringtonDarkholme It looks like Babel is in play.

realyze commented 7 years ago

@aluanhaddad Perfect, that does the trick, thanks so much! I'm using Meteor with the ecmascript package so that was the problem.

nerdybeast commented 7 years ago

Need to change:

import express from "express";

to

import express = require('express');

This is how you have to import commonjs modules in Typescript.

kahurangitama commented 6 years ago

I'm doing this like:

import * as express from "express";
nerdybeast commented 6 years ago

@pavlosadovyi don't quote me on this because I haven't looked into it but I think your example works for Express v5 but I don't think v4 had the typings definitions that allowed the ES6 import syntax.

I do it your way today because I'm now using Express v5.

aluanhaddad commented 6 years ago

@kahurangitama you should avoid that. Either use

import express = require('express');

or

import express from 'express';

It is invalid to call a Module Namespace Object, so code like

import * as express from 'express';
const app = express();

are currently allowed but are invalid ES and therefore are already broken or likely to break.

weber-d commented 6 years ago

@aluanhaddad But import express from "express"; seems to work but VS Code doesn't recognize this as valid:

message: 'The module ""/node_modules/@types/express/index"" doesn't contain a default export. It's not related to the known caching issues. After re-opening VS Code, the error is still present.