sequelize: Class constructor Model cannot be invoked without 'new' and how getter v4 work?

Hi all, I using v4 to defined my model as:

@Options({
    sequelize,
    tableName: 'V2_category',
    timestamps: false
})
@Attributes({
    id: {
        type: DataTypes.INTEGER,
        allowNull: false,
        primaryKey: true,
        autoIncrement: true
    },
    name: DataTypes.STRING,
    name_vi: DataTypes.STRING,
    code: DataTypes.STRING,
    type: DataTypes.STRING,
    created_at: DataTypes.DATE,
    updated_at: DataTypes.DATE,
})
export class V2Category extends Model {
    get fullName() {
        return this.name + '-' + this.name_vi;
    }

    set fullName(fullName) {
        const names = fullName.split(' ');
        this.name = names.pop();
        this.name_vi = names.join(' ');
    }
}

and i import in others: import {V2Category as category} from '../models/V2_category';

my query : findCategoryById (id) { return category.findOne({ where: { 'id': id } }); }

When run i got an error:

Unhandled rejection TypeError: Class constructor Model cannot be invoked without ‘new’

However, i add { where: { 'id': id }, raw: true } my code working but i can’t use getter function fullName. Could you tell me where my mistake and how to fix it? Thanks

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 10
  • Comments: 30 (5 by maintainers)

Commits related to this issue

Most upvoted comments

Intypescript case, my solution was to change target from es5 to es6

{
  "compilerOptions": {
    "target": "es6", // <=
    // ...
  }
}

In JavaScript, a class is a function.

I think it has something to do with the way babel transpiles the code. After I changed my .babelrc file to this:

{
  "presets": [
    ["env", {
      "targets": {
        "node": "current"
      }
    }]
  ]
}

it works as expected.

Mine got solved via:

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "node": true
        }
      }
    ]
  ]
}

Im not using a transpiler and i have this error as well

Intypescript case, my solution was to change target from es5 to es6

{
  "compilerOptions": {
    "target": "es6", // <=
    // ...
  }
}

Works for me! Thanks

Same issue here and my .babelrc is:

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "node": "current"
        }
      }
    ]
  ]
}

Any other suggestions to solve this?

It turns out that an ES6-class transpiled by babel can’t extend a real ES6 class (The Sequelize.Model ES6-class for example).

So class MyEntity extends Sequelize.Model { ... } won’t work if MyEntity is transpiled into ES5.

See https://stackoverflow.com/questions/36577683/babel-error-class-constructor-foo-cannot-be-invoked-without-new

The solution i used, was to use es2015-node5 instead of es2015. But ONLY on the server, of course, not on the client - i.e. not when transpiling for the browser. So i didn’t put this in my .babelrc, but added it to the “build-server” command-line scripts in package.json instead: babel .... --no-babelrc --presets=es2015-node5,stage-0,react.

@juhaelee says:

You just need to use the env preset package instead of es2015

  "presets": [
    ["env", {
      "targets": {
        "node": "current"
      }
      }],
    "stage-1"
  ],
  "plugins": []
}

I had the same error with typescript and it was fixed when I updated the tsconfig.json changing the es5 for es6

“compilerOptions”: { “target”: “es6”, /* Specify ECMAScript target version: ‘ES3’ (default), ‘ES5’, ‘ES2015’, ‘ES2016’, ‘ES2017’, ‘ES2018’, ‘ES2019’, ‘ES2020’, or ‘ESNEXT’. / “module”: “commonjs”, / Specify module code generation: ‘none’, ‘commonjs’, ‘amd’, ‘system’, ‘umd’, ‘es2015’, ‘es2020’, or ‘ESNext’. */

Hi guys, I have the same issue with tsc (TypeScript compiler).

tscconfig.json

{
  "compilerOptions": {
    "target": "ES6",
    "module": "CommonJS",
    "moduleResolution": "node",
    "lib": ["ES5", "ES6"],
    "declaration": true,
    "outDir": "./build",
    "strict": true,
    "esModuleInterop": true,
    "allowJs": false,
    "allowSyntheticDefaultImports": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "strictPropertyInitialization": false,
    "sourceMap": true
  },
  "include": ["src"],
  "exclude": ["node_modules"]
}

version

{
  "sequelize": "^5.21.6",
  "ts-node": "^8.10.1",
  "typescript": "^3.7.2"
}

model

import { Model, DataTypes } from 'sequelize';
import sequelize from './';
import { OrderStatus } from '../components/constants';

class Order extends Model {
  public id!: number;
  public total!: number;
  public finalTotal!: number;
  public status: OrderStatus;
  public start_date: Date;
  public end_date: Date;
  public created_at: Date;
  public updated_at: Date;
}

Order.init({
  id: {
    type: DataTypes.UUID,
    primaryKey: true,
    defaultValue: DataTypes.UUIDV4
  },
  total: {
    type: DataTypes.INTEGER,
    allowNull: true,
  },
  finalTotal: {
    type: DataTypes.INTEGER,
    allowNull: true,
    validate: {
      len: {
        args: [2, 5],
        msg: 'Name must be from 2 to 5 characters in length'
      },
    }
  },
  status: {
    type: DataTypes.ENUM(OrderStatus.InProcess, OrderStatus.Done)
  },
}, {
  sequelize,
  tableName: 'orders',
})

export default Order;

sequelize.import

const modelsPath = `${__dirname}/../src/models`;
  const models = fs
    .readdirSync(modelsPath)
    .filter((filename: string) => /model.ts$/.test(filename))
    .reduce((total: any, filename: string) => {
      const model = sequelize.import(path.join(modelsPath, filename));
      total[capitalize(model.name)] = model;
      return total;
    }, {});

  // Sets up the associations for each model.
  Object.keys(models).forEach((modelName: string) => {
    if ('associate' in models[modelName]) {
      models[modelName].associate(models);
    }
  });

error

TypeError: Class constructor Order cannot be invoked without 'new'
      at Sequelize.import (node_modules/sequelize/lib/sequelize.js:486:38)
      at /home/cuongw/Workspace/SaveMoney/service-template/test/utils.ts:18:37
      at Array.reduce (<anonymous>)
      at Object.exports.prepareModels (test/utils.ts:17:6)
      at Object.exports.loadFixtures (test/utils.ts:35:18)
      at Context.<anonymous> (test/order.test.ts:16:11)
      at processImmediate (internal/timers.js:456:21)

Please tell me a solution. Thank all.

I resolved my issue. I used require instead of sequelize.import. 😓

For anyone who comes to this and the reason was not transpiling. For me it was because I was exporting my models as classes, and the line from the generated models/index.js :

const model = sequelize['import'](path.join(__dirname, file))

was causing the error. Once I changed that line to:

let model = require(path.join(__dirname, file));

It was fixed

Turns out in my case, I had a previously created model in the models folder that was causing things to break:

const Sequelize = require('sequelize')
const db = require('../sequelize')

const Post = db.define('post', {
    title: Sequelize.STRING(255),
    body: Sequelize.TEXT('long'),
    excerpt: Sequelize.STRING(500),
    tags: Sequelize.STRING(500),
    slug: Sequelize.STRING(255),
    thumbnail_path: Sequelize.STRING(255),
    hero_path: Sequelize.STRING(255),
    updatedAt: Sequelize.DATE
})

module.exports = Post

This was preventing the file from being read correctly by sequelize and causing the error listed in this thread. Advice for others: Make sure all of your code inside of your models folder is valid and from examples.

let model = require(path.join(__dirname, file))

I am having the same issue, changed the appropriate line, still no luck.

I had the same error with typescript and it was fixed when I updated the tsconfig.json changing the es5 for es6

“compilerOptions”: { “target”: “es6”, /* Specify ECMAScript target version: ‘ES3’ (default), ‘ES5’, ‘ES2015’, ‘ES2016’, ‘ES2017’, ‘ES2018’, ‘ES2019’, ‘ES2020’, or ‘ESNEXT’. / “module”: “commonjs”, / Specify module code generation: ‘none’, ‘commonjs’, ‘amd’, ‘system’, ‘umd’, ‘es2015’, ‘es2020’, or ‘ESNext’. */

Thank for your reply. I used ES6 for target but it doesn’t work.