开发者问题收集

TypeError:没有“new”就无法调用类构造函数模型

2021-02-22
38955

我在一个应用中将 Sequelize Node JavaScript 一起使用。如您所知,当您执行 sequelize-init 时,它会创建 config migrations models seeders 文件夹。在 models 文件夹中,有一个 index.js 文件(由 cli 生成),它负责从当前文件夹中读取所有模型及其关联:

index.js

'use strict';

const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const sequelize = require('../database/connection');
const db = {};

fs
  .readdirSync(__dirname)
  .filter(file => {
    return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js');
  })
  .forEach(file => {
    const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes);
    db[model.name] = model;
  });

Object.keys(db).forEach(modelName => {
  if (db[modelName].associate) {
    db[modelName].associate(db);
  }
});

db.sequelize = sequelize;
db.Sequelize = Sequelize;

module.exports = db;

当我运行我的应用程序时,出现错误: TypeError: Class construction model could be called without 'new' 在第 17 行,该语句为: var model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes); 阅读一些与此问题相关的 帖子 ,我发现我需要安装 @babel/preset-env 软件包以及 @babel/cli、@babel/core、@babel/node 。我还在根目录中创建了一个 .babelrc 文件,其中包含以下代码:

.babelrc

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

并将 package.jsonscripts 标签的 start 选项更新为: “nodemon --exec babel-node app.js” (我不使用 webpack)

但当我运行应用程序时,错误仍然出现。我遗漏了什么或没有正确设置?

3个回答

注意:如果您想知道,请查看最后的“为什么”部分。

问题

问题是 ES6 类 => 没有完整功能转换为 ES5!Sequelize 依赖于某些功能

或者

使用 Sequelize.import 代替 require!不要! (Babel 或任何转译器与 require(或 es import)一起工作,而 sequelize.import 的工作方式导致了问题!)!

回答

我猜你正在使用

export class Course extends Model {} // <== ES6 classes

Course.init({

你的 babel 配置是导致该问题的原因!

你可以在这个 github 线程上检查 评论

这对那个人有用

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

或者

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

评论

让 babel 使用 ES6 类!

请注意, 另一方面 你只需 坚持 sequelize.define() 方式

export const User = sequelize.define('User', {
  // Model attributes are defined here
  firstName: {
    type: DataTypes.STRING,
    allowNull: false
  },

它将在 ES5 中正常工作!

不要使用 Sequelize.import 导入模型

如果你正在这样做,那么不要!使用 require 或 es import !转译器不直接处理 Sequelize.import!而且它似乎会导致问题

评论 显示

对我来说,这是因为带有 Typescript 的 ES6

Typescript

默认目标是 ES5

将其更改为 ES6+ !一切开始工作!

例如

"target": "ES2021", 

ES5 与 sequelize.define 一起工作

要知道 ES5 与 sequelize.define 一起工作得很好!

在此处输入图像描述

带有 Class extends 的 ES5 不起作用

在此处输入图像描述

插图

在此处输入图片说明

ES6+ 始终有效

在此处输入图片说明

在此处输入图片说明

为什么!Babel 通常无法正确转译!! ???

你可以在这个 github 评论

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.

这里是 stackoverflow 的答案,解释得更好: https://stackoverflow.com/a/36657312/7668448

Due to the way ES6 classes work, you cannot extend a native class with a transpiled class. If your platform supports native classes

您可以看到更多关于为什么以及如何 将 ES6 类转换为 ES5 以支持完整功能和兼容性 的深度元素!在以下链接中:

https://github.com/microsoft/TypeScript/issues/17088

https://github.com/microsoft/TypeScript/issues/15397

这里有一篇文章( comparing-different-ways-of-transpiling-es6-class-to-es5 )对这个主题进行了更详细的介绍

Mohamed Allal
2021-07-31

如果 tsconfig.json 文件中的“target”中有“es5”,则更改为“es6”。 (这对我有用,我需要编译器中的 es6。)

"compilerOptions": {
    "target": "es6"
}
Cristian Gómez
2023-06-15

就我而言,这是因为出于某种原因,我的实体中的构造函数方法被注释掉了。 所以我直接取消注释,然后它就起作用了:

@Table
export class Kondo extends Model {

constructor(partial?: Partial<Kondo>) {
  super();
    
  if (partial)
    Object.assign(this, partial);
}
Victor Souto
2024-07-10