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

问题描述 投票:0回答:3

我在一个应用程序中将 SequelizeNodeJavaScript 一起使用。如您所知,当您执行

sequelize-init
时,它会创建 configmigrationsmodelsseeders 文件夹。在 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 constructor model cannot be invoked without 'new' 在第 17 行,这是语句: var model = require(path.join(__dirname, file))(sequelize ,Sequelize.DataTypes); 阅读一些与此问题相关的 posts,我发现我需要安装

@babel/preset-env
包以及
@babel/cli, @babel/core, @babel/node
。我还在根目录下创建了一个
.babelrc
文件,其中包含以下代码:

.babelrc

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

并将

start
内的
scripts
标签的
package.json
选项更新为:
"nodemon --exec babel-node app.js"
(我不使用 webpack)

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

javascript node.js ecmascript-6 sequelize.js babeljs
3个回答
23
投票

注意:最后检查“原因”部分!如果你想知道的话。

问题

问题是 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!这似乎会引起问题

评论表明

对我来说,这是因为 ES6 和 Typescript

打字稿

默认目标是

ES5

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

例如

"target": "ES2021", 

带有sequelize.define 的ES5 可以工作

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

enter image description here

带有类扩展的 ES5 不起作用

enter image description here

插图

enter image description here

ES6+ 始终有效

enter image description here

enter image description here

为什么! Babel 通常不会正确转译! ???

你可以在这个github中看到评论

事实证明,由 babel 转译的 ES6 类无法扩展真正的 ES6 类(例如 Sequelize.Model ES6 类)。
因此,如果 MyEntity 被转译为 ES5,则 class MyEntity extends Sequelize.Model { ... } 将不起作用。

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

由于 ES6 类的工作方式,您无法使用转译类来扩展本机类。如果你的平台支持原生类

您可以看到更多关于为什么以及如何可能这样的

transpilation of ES6 Class to ES5 can be done to support full features and compatiblity
的深度元素!在下面的链接中:

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

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

这里有一篇文章(比较 es6-class-to-es5 的不同转换方式),详细介绍了该主题


0
投票

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

"compilerOptions": {
    "target": "es6"
}

0
投票

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

@Table
export class Kondo extends Model {

constructor(partial?: Partial<Kondo>) {
  super();
    
  if (partial)
    Object.assign(this, partial);
}
© www.soinside.com 2019 - 2024. All rights reserved.