81

I have a class written in Javascript ES6. When I try to execute nodemon command I always see this error TypeError: Class constructor Client cannot be invoked without 'new'

The full error is mentioned below:

/Users/akshaysood/Blockchain/fabricSDK/dist/application/Transaction.js:45
        return (0, _possibleConstructorReturn3.default)(this, (FBClient.__proto__ || (0, _getPrototypeOf2.default)(FBClient)).call(this, props));
                                                                                                                              ^

TypeError: Class constructor Client cannot be invoked without 'new'
    at new FBClient (/Users/akshaysood/Blockchain/fabricSDK/dist/application/Transaction.js:45:127)
    at Object.<anonymous> (/Users/akshaysood/Blockchain/fabricSDK/dist/application/Transaction.js:195:14)
    at Module._compile (module.js:641:30)
    at Object.Module._extensions..js (module.js:652:10)
    at Module.load (module.js:560:32)
    at tryModuleLoad (module.js:503:12)
    at Function.Module._load (module.js:495:3)
    at Module.require (module.js:585:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (/Users/akshaysood/Blockchain/fabricSDK/dist/routes/users.js:11:20)

What I am trying to do is, I have created a class and then created an instance of that class. Then I am trying to export that variable.

The class structure is defined below:

class FBClient extends FabricClient{

    constructor(props){
        super(props);
    }

<<< FUNCTIONS >>>

}

How I am trying to export the variable ->

var client = new FBClient();
client.loadFromConfig(config);

export default client = client;

You can find the full code here --> Link. Code generated by Babel --> Link.

Alexander Solonik
  • 9,838
  • 18
  • 76
  • 174
Akshay Sood
  • 6,366
  • 10
  • 36
  • 59
  • I'm not sure that you can export the instance of a class. I think you have to export the class, import it in another, then create the instance there – bwalshy Aug 15 '18 at 13:54
  • 8
    @bwalshy - You can export any value, including an instance of a class. – T.J. Crowder Aug 15 '18 at 13:55
  • @T.J.Crowder This code can not be run online as it requires Blockchain module. – Akshay Sood Aug 15 '18 at 13:58
  • 2
    @AkshaySood - The error is clearly not about blockchain stuff, it's about basic class definition and instantiation. Please read that MCVE link. You're not expected to post all your code. You're expected to work through a process producing a minimal replicating example. You haven't even shown us the class where the error is occurring. – T.J. Crowder Aug 15 '18 at 14:03
  • 2
    Are you using Babel to transpile your code? [(possibly related issue, but just a guess)](https://github.com/sequelize/sequelize/issues/7840) – Pointy Aug 15 '18 at 14:04
  • @Pointy Yes I am using Babel – Akshay Sood Aug 15 '18 at 14:06
  • Notice that you should not use `class` syntax anyway if you want your module to export a singleton object. If you think you need instances, then you should export the class itself. – Bergi Aug 15 '18 at 15:09

9 Answers9

114

The problem is that the class extends native ES6 class and is transpiled to ES5 with Babel. Transpiled classes cannot extend native classes, at least without additional measures.

class TranspiledFoo extends NativeBar {
  constructor() {
    super();
  }
}

results in something like

function TranspiledFoo() {
  var _this = NativeBar.call(this) || this;
  return _this;
}
// prototypically inherit from NativeBar 

Since ES6 classes should be only called with new, NativeBar.call results in error.

ES6 classes are supported in any recent Node version, they shouldn't be transpiled. es2015 should be excluded from Babel configuration, it's preferable to use env preset set to node target.

The same problem applies to TypeScript. The compiler should be properly configured to not transpile classes in order for them to inherit from native or Babel classes.

Estus Flask
  • 206,104
  • 70
  • 425
  • 565
  • 3
    As the answer says. Change Babel configuration to not transpile to ES5. `es2015` preset is responsible for this behaviour. – Estus Flask Aug 15 '18 at 14:45
  • If I do not transpile ES6 into ES5 using Babel. It throws error :unexpected token import: – Akshay Sood Aug 15 '18 at 14:46
  • 4
    The manual covers that, https://babeljs.io/docs/en/babel-preset-env/ . Use 'target node'. – Estus Flask Aug 15 '18 at 14:50
  • estus. Do you know how to use ES6 in Nodejs without Babel? – Akshay Sood Aug 15 '18 at 15:46
  • Just use it, all features except ES modules are available, http://node.green/ . ES modules are experimental and need .mjs extension, you may want to use `require` and `module.exports` for now. Babel is useful only for using features that are not there, like class fields and decorators. – Estus Flask Aug 15 '18 at 15:50
  • Ok So that means we can not use `export` & `import` without babel? Can we use `classes` & `constructors` and other features without babel? – Akshay Sood Aug 15 '18 at 15:52
  • Yes, we can use export and import, but this feature is experimental and isn't very practical in its current implementation, see https://nodejs.org/api/esm.html , I'd suggest to stick to CJS modules for real work. Yes, we can use them, see http://node.green/ – Estus Flask Aug 15 '18 at 15:57
  • For me i had to remove `'use babel';`! Thanks!! – NHDaly Dec 28 '18 at 05:39
  • How stupid is it that `typeof class A {} === 'function'` yet `A.call()` throws an error? – jchook Oct 14 '19 at 01:57
  • 1
    @jchook Technically it works like `function A() { if (!new.target) throw new Error('cannot be invoked without new') }`. `A` has its terms but it's definitely a function. – Estus Flask Feb 21 '20 at 19:34
  • Please do keep in mind that, while this would work okay for a node (and that's enough to answer the question), it won't help much if you're trying to target a browser. – Haroldo_OK Feb 27 '20 at 14:40
  • 2
    @Haroldo_OK Indeed, at least if this means the support of legacy browsers (browser app shouldn't necessarily be ES5 in 2020). If there's a class that extends built-in class (Error, Promise, etc.), it should be extended in a special way to be compatible with ES5, this is covered in other questions on SO. If a class extends native ES6 class, it's the existence of untranspiled class in ES5 app that is a real issue. – Estus Flask Feb 27 '20 at 16:40
33

I was transpiling not Javascript but Typescript, and ran into the same problem.

I edited the Typescript compiler config file, tsconfig.json, to generate ES2017 Javascript code:

{
    "compilerOptions": {
        "target": "ES2017",

instead of whatever the default is, ES2015? — then all worked fine.

(Maybe this answer can be helpful for people who use Typescript and find this question when they search for the same error message, like I did.)

KajMagnus
  • 11,308
  • 15
  • 79
  • 127
17

For those who are using ts-node, it could be possible that your tsconfig.json is unable to be loaded by ts-node.

  1. Make sure you've set the below option for tsconfig.json:
    {
        "compilerOptions": {
            "target": "ES6",
            ...
        }
    }
  1. Try ts-node --script-mode or use --project to specify the path of your tsconfig.json.
Devo
  • 1,004
  • 11
  • 10
8

In package.json you can use targets configuration with @babel/preset-env. set the esmodules as 'true'.

Below is the example how I am using in my file:

  "babel": {
    "presets": [
      [
        "@babel/preset-env",
        {
          "targets": {
            "esmodules": true
          }
        }
      ],
      "@babel/preset-react",
      "@babel/preset-flow"
    ],
    "plugins": [
      "@babel/plugin-proposal-class-properties"
    ]
  },
Hakan Dilek
  • 2,178
  • 2
  • 23
  • 35
Chandan Aswal
  • 89
  • 1
  • 2
3

For Angular 9+ this can be probably a matter of using typescript compilation flags also:

  • downlevelIteration
  • importHelpers

More info hereL https://www.typescriptlang.org/tsconfig#downlevelIteration.

Try to use this flags in your tsconfig.josn:

{
    "compilerOptions": {
        ...
        "downlevelIteration": true,
        "importHelpers": true,
        ...
    }
}

Without "importHelpers": true it should also works.


This solution is mostly for Angular 9+ and ngcc compiler - this was an issue that occur for Angular 11. A custom configuration (custom ng-packgr config - Angular CLI library generating was introduced in Angular 6) for packages was maintained since there was Angular 4+ in the project. After miagration these packages to Angular 9+ libraries (projects folder) the error started occuring. I found that these flags (sctrictly downlevelIteration) solve exactly the problem.

TwaPaw
  • 31
  • 2
1

If you are not using babel and simple typescript. I got the error in material. Try to reduce the versions and bring them down to similar versions. My packages were having variety of versions.I solved the issue by lowering the package versions of packages like cdk, material.

Check the image of my final package.json

jizhihaoSAMA
  • 12,336
  • 9
  • 27
  • 49
1

Check your "entities" array in appmodule.ts I also missed that. When I kept the entity name that is used in query, issue resolved. Hope this answer helps.

0

i used wrote before my ObjectId in nextjs and it worked.

  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jul 07 '23 at 20:35
-9

I hope you have already been able to solve your problem, here is my solution for this error:

class indexRoutes
{
    
    public  router: Router= Router();
}
const INDEX_ROUTES = new indexRoutes();
export default INDEX_ROUTES.router;
Tyler2P
  • 2,324
  • 26
  • 22
  • 31
Alejandro
  • 83
  • 1
  • 2