Skip to content

JavaScript error“TypeError: Class constructor X cannot be invoked without 'new'”

The code stops with TypeError: Class constructor User cannot be invoked without 'new' (Chrome, Node.js) or Cannot call a class constructor User without |new| (Safari). Something called a class as a plain function. Sometimes that is your own code; often it is code compiled to ES5 by TypeScript (or a very old Babel), extending a class from a package that ships modern JavaScript.

Short answer

If the stack trace points at your code, add new: new User(data), not User(data), and use (x) => new Row(x) where a function is expected. If it points at compiled output and appeared after a package update, your build targets ES5 while the package now ships real classes: set "target" to "ES2017" or later in tsconfig.json.

Why the class was called without new, and the fix

  1. 01

    Calling a class like a function

    “All class constructors must be called with new.” MDN, TypeError: class constructors must be invoked with 'new'

    A class can only be constructed. Add new where it is created.

    // wrong
    const user = User(data);
    
    // right
    const user = new User(data);
  2. 02

    A class passed where a function is expected

    “However, class constructors are always constructors and cannot be called as normal functions.” MDN, TypeError: class constructors must be invoked with 'new'

    rows.map(Row), a callback, or a factory option calls the class without new. Wrap it in a function that constructs it.

    // wrong
    const items = rows.map(Row);
    
    // right
    const items = rows.map((r) => new Row(r));
  3. 03

    TypeScript compiling to ES5 and extending a real class

    “Modern browsers support all ES6 features, so ES6 is a good choice.” TypeScript, TSConfig: target

    With target ES5, class Child extends Base becomes a function that calls Base.call(this). If Base comes from a package that ships real ES2015+ classes, that call throws. Raise the target so your classes stay classes. Current Babel handles this case; a very old Babel (6) or a custom ES5 transform can fail the same way, so update it and drop IE-era targets.

    // tsconfig.json
    {
      "compilerOptions": {
        "target": "ES2017"
      }
    }
  4. 04

    Old-style inheritance with Parent.call(this)

    Pre-class code inherits with Parent.call(this, ...) and Object.create. Once Parent is rewritten as a class, that call throws. Convert the child to class Child extends Parent with super().

    class Child extends Parent {
      constructor(name) {
        super(name);
      }
    }

Checked against the vendor’s docs on : MDN: TypeError: class constructors must be invoked with 'new'; TypeScript: TSConfig target.

Rather hand it over?

Fixed scope, fixed price, paid upfront. The work happens in writing; no call needed.

Related: “x is not a constructor” · JavaScript “x is not a function” · TypeScript “Type is not assignable to type”

Questions

More on this error

Why did it start after updating a package?

The new version ships real ES2015+ classes instead of compiled functions. If your own code is compiled to ES5 and extends one of its classes, the compiled child calls the parent without new. Raising your build target fixes it.

Is this the same as x is not a constructor?

No, it is the opposite. x is not a constructor means new was used on something that cannot be constructed. This error means a class was called without new.

Can you fix it for me?

If one bug is the whole problem, the App Fix Ticket covers it: a written diagnosis first, then the fix. If the app has more going on, the Launch Check is a written check of the whole app. Each issue found is rated critical, high, medium or low, with where it is and how it was confirmed. No issues worth fixing, no charge. If the Launch Check finds nothing rated medium or higher, Simon refunds the full $450. You keep the report either way. This applies to the first 10 Launch Checks bought after October 30, 2026.

A different error?

Describe it and get a written quote

Send the error and what you were doing. You get a written scope, a fixed price and a timeline; Simon replies by email, usually within one business day.