TypeError:没有“new”就无法调用类构造函数模型
我在一个应用中将
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.json
内
scripts
标签的
start
选项更新为:
“nodemon --exec babel-node app.js”
(我不使用 webpack)
但当我运行应用程序时,错误仍然出现。我遗漏了什么或没有正确设置?
注意:如果您想知道,请查看最后的“为什么”部分。
问题
问题是 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 )对这个主题进行了更详细的介绍
如果 tsconfig.json 文件中的“target”中有“es5”,则更改为“es6”。 (这对我有用,我需要编译器中的 es6。)
"compilerOptions": {
"target": "es6"
}
就我而言,这是因为出于某种原因,我的实体中的构造函数方法被注释掉了。 所以我直接取消注释,然后它就起作用了:
@Table
export class Kondo extends Model {
constructor(partial?: Partial<Kondo>) {
super();
if (partial)
Object.assign(this, partial);
}