Class constructor cannot be invoked without 'new' - typescript with commonjs
Asked Answered
I

3

34

I am making server side chat with colyseus (node game server framework). Im using typescript with module:commonjs because colyseus is built upon commonjs.

I have class ChatRoom that extends Colyseus.Room. At run-time I get this error:

Class constructor Room cannot be invoked without 'new'.

And the trouble in javascript:

function ChatRoom() {
   return _super !== null && _super.apply(this, arguments) || this;
}

from typescript class:

import {Room} from "colyseus";

export class ChatRoom extends Room {

    onInit(options) {
        console.log("BasicRoom created!", options);
    }

    onJoin(client) {
        this.broadcast(`${ client.sessionId } joined.`);
    }

    onLeave(client) {
        this.broadcast(`${ client.sessionId } left.`);
    }

    onMessage(client, data) {
        console.log("BasicRoom received message from", client.sessionId, ":", data);
        this.broadcast(`(${ client.sessionId }) ${ data.message }`);
    }

    onDispose() {
        console.log("Dispose BasicRoom");
    }
  }

The error is easily skipped when troubled row is removed after compilation. But the base class is not created and this is not a complete solution.

I googled the issue and it seems to relate to babel transpiler, though I don't use babel. I only use tsc / tsconfig.json.

Inshrine answered 6/5, 2018 at 18:50 Comment(0)
L
80

TypeScript transpiles a class to its ES5 counterpart, but this way it's necessary that entire class hierarchy is transpiled to ES5.

In case parent class is untranspiled (native class or imported ES6 class, including the ones that were transpiled with Babel), this won't work, because TypeScript relies on var instance = Parent.call(this, ...) || this trick to call parent constructor, while ES6 classes should be called only with new.

This problem should be solved in Node.js by setting TypeScript target option to es6 or higher. Modern Node.js versions support ES6 classes, there is no need to transpile them.

The same problem applies to Babel.

Lesbianism answered 6/5, 2018 at 19:10 Comment(3)
Thanks. This works: tsconfig.compilerOptions: {target : "es6",..}Inshrine
...or also, in case you need es5 support, making sure that all the hierarchy is compiled with target: es5. my two cents!Kenzie
Here's a table of which target to use for your version of Node github.com/microsoft/TypeScript/wiki/Node-Target-MappingChaldean
S
31

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.
Syringe answered 28/5, 2020 at 9:37 Comment(5)
This solved my issue! I had to switch over from ES5 to ES6 and it workedDerose
Thanks a lot for the answer. I tried this but I am unable to follow what you are mentioning in Step-2. I am using Nuxt.js. https://mcmap.net/q/245225/-nuxt-throws-class-constructor-i-cannot-be-invoked-without-39-new-39/7584240Elvia
@Elvia Are you using ts-node? When using ts-node, we call something like ts-node ./index.ts to start our app. And according to my answer, we can use ts-node --script-mode ./index.ts instead.Syringe
Using ts-node --project tsconfig.json did it for me!Servitude
Unfortunately, I created a tsconfig.json as you suggested but I am still getting that error.Backhanded
G
4

I came across the same problem using javascript, webpack, and babel (but no TypeScript).

I found a solution based on ES6/Babel Class constructor cannot be invoked without 'new'

I needed to explicitly include colyseus in my babel loader. Below is the snippet in my webpack config file:

  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        include: /colyseus/,
        use: {
          loader: "babel-loader"
        }
      }
    ]
  },
Greisen answered 11/3, 2019 at 1:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.