1

I have this code in TS to create an instance of ConnectRoles Middleware in Express:

let user = new ConnectRoles(config);

this is what the middleware expects to be able to initialize, a simple call to a constructor, however after transpiling, the resulting javascript code looks like this:

let user = new connect_roles_1.default(config);

I am importing this class in TS using:

import ConnectRoles from "connect-roles";

which translates to:

const connect_roles_1 = require("connect-roles");

in JS, is it possible that the way in which I am instantiating/importing the class may be the issue here? I can remove manually the "default" method that is causing errors in the code in the JS, but this defeats the purpose of using a transpiler, specially if things like this start happening more often.

One more thing, this is my tsconfig.json:

{
  "compilerOptions": {
      "baseUrl": ".",
      "paths": { "*": ["types/*"] },
      "target": "es2015",
      "module": "commonjs",
      "moduleResolution": "node",
      "isolatedModules": false,
      "jsx": "react",
      "experimentalDecorators": true,
      "emitDecoratorMetadata": true,
      "declaration": false,
      "noImplicitAny": false,
      "noImplicitUseStrict": false,
      "removeComments": true,
      "noLib": false,
      "preserveConstEnums": true,
      "suppressImplicitAnyIndexErrors": true,
      "outDir": "app",
      "sourceMap": true,
      "watch": true
  },
  "exclude": [
      "node_modules",
      "typings/browser",
      "typings/browser.d.ts",
  ],
  "compileOnSave": true,
  "buildOnSave": true,
  "atom": {
      "rewriteTsconfig": false
  }
}

Any ideas will be very appreciated, thanks!

d-_-b
  • 21,536
  • 40
  • 150
  • 256
Will de la Vega
  • 536
  • 1
  • 5
  • 17

2 Answers2

3

You should think of typescript files as modules, which export objects.


import {x, y, z} from "module" is how you access these exports.

When you use import x from "module", you're actually just importing the default from the module.

import x from "module" is simply an alias for import {default as x} from "module"

module itself isn't one export. Which is why you can also still import other exports:

import default, {x, y, z} from "module"


module.ts

export const x = /*...*/;
export const y = /*...*/;
export const z = /*...*/;
export const default = /*...*/;

In the past, you could export one default like so:

module.exports = /*...*/;

However, now you should think of exports strictly following the form:

{
   exportName: /*...*/,
   default: /*...*/
}

Many modules still use the old convention to export a default: module.exports = /*...*/;

In this case, you can import them using import * as x from "module";

Tobiq
  • 2,489
  • 19
  • 38
3

As Tobiq says, import ConnectRoles from "connect-roles" is trying to import a default export. The module you're trying to import does not use a default export, though; instead, it uses module.exports = ConnectRoles.

Here are three different import styles and the compiled results that they produce:

import ConnectRolesImport from 'connect-roles';
const connectRolesImport = new ConnectRolesImport(); // error!

import * as ConnectRolesImportAll from 'connect-roles';
const connectRolesImportAll = new ConnectRolesImportAll();

import ConnectRolesRequire = require('connect-roles');
const connectRolesRequire = new ConnectRolesRequire();

Compiled Result:

var connect_roles_1 = require("connect-roles");
var connectRolesImport = new connect_roles_1["default"]();

var ConnectRolesImportAll = require("connect-roles");
var connectRolesImportAll = new ConnectRolesImportAll();

var ConnectRolesRequire = require("connect-roles");
var connectRolesRequire = new ConnectRolesRequire();

Here is one of the TypeScript team members talking about the difference between the import xxx as... and import xxx = require... syntax. That and this answer's comments will help you choose which to use.

Shaun Luttin
  • 133,272
  • 81
  • 405
  • 467
  • `require` is undefined in typescript. – Tobiq May 12 '19 at 21:25
  • https://stackoverflow.com/questions/12742082/nodejs-require-inside-typescript-file – Tobiq May 12 '19 at 21:28
  • @Tobiq That happens if we compile without setting `module` to `commonjs`. The question is asking about an express application, so it is reasonable to assume the use of `commonjs` as the module system. – Shaun Luttin May 12 '19 at 21:30
  • Which is feasible. Typescript extends experimental-modules, where `require` is deprecated. – Tobiq May 12 '19 at 21:32
  • I didn't understand your most recent comment. – Shaun Luttin May 12 '19 at 21:33
  • `require` is deprecated. – Tobiq May 12 '19 at 21:35
  • The deprecation of import/require is true @Tobiq but is somewhat controversial: https://github.com/Microsoft/TypeScript/issues/11340 and https://stackoverflow.com/a/35706271/1108891 both talk about its use cases. – Shaun Luttin May 12 '19 at 21:57
  • 1
    thanks for your answer, both are great, I upvote both of them but had to mark as answer the one from Shaun Luttin as he was even more specific to my case. Thanks also to Tobiq, your answer helped me to better understand how to treat imports and exports in typescript files vs. node files. Thanks guys. – Will de la Vega May 13 '19 at 03:53