node.js - Typescript kullanarak bir Sequelize Modelinde örnek yöntemler oluşturma
Sequelize Model sınıfını diğer örnek yöntemleri eklemek için genişletmek istiyorum ama TypeScript sürekli olarak "Model türünde 'prototype' özelliği mevcut değil" diye hata veriyor
const MyModel = (sequelize: Sequelize.Sequelize, dataTypes: Sequelize.DataTypes) => {
const User = sequelize.define<Instance, Attribute>(
"users",
{
id: {
type: dataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
email: {
type: dataTypes.STRING
},
...
},
{
tableName: "users",
...
},
);
User.prototype.verifyUser = function(password: string) {
...
};
return User;
};
User.prototype.verifyUser işlev görmesini bekliyorum ama TypeScript hata veriyor. Tip eklemeyi nasıl yapabilirim?
Cevap #1
@Shadrech'in yorumunu takiben, benim bir alternatifim var (daha az geçici ve soyut).
export interface UserAttributes {
...
}
export interface UserInstance extends Sequelize.Instance<UserAttributes>, UserAttributes {
}
interface UserModelInstanceMethods extends Sequelize.Model<UserInstance, UserAttributes> {
// Came to this question looking for a better approach to this
// You'll need root's definitions for invocation and prototype's for creation
verifyPassword: (password: string) => Promise<boolean>;
prototype: {
verifyPassword: (password: string) => Promise<boolean>;
};
}
const MyModel = (sequelize: Sequelize.Sequelize, dataTypes: Sequelize.DataTypes): UserModelInstanceMethods => {
const User = sequelize.define<UserInstance, UserAttributes>(
...
) as UserModelInstanceMethods;
User.prototype.verifyUser = function(password: string) {
...
};
return User;
}
Modelinizi kullanarak:
sequelize.query("SELECT ...").then((user: UserInstance & UserModelInstanceMethods) => {
user.verifyPassword(req.body.password) // <= from UserModelInstanceMethods
user.getDataValue('name') // <= from UserInstance
})
Cevap #2
Ana Sequelize TypeScript Dokümanı'na göre, bence bunu uygulamanın en iyi yolu, DataTypes.VIRTUAL kullanmak ve modeli oluşturma arayüzünde özelliği TypeScript Omit yardımcı aracı ile atlamaktır.
Önemli! Issue#11675'i unutma!
- https://stackoverflow.com/a/69289067/717267
- https://github.com/sequelize/sequelize/issues/11675
Basit bir örnek:
import {
Sequelize,
Model,
ModelDefined,
DataTypes,
Optional,
// ...
} from 'sequelize';
interface ProjectAttributes {
id: number;
ownerId: number;
name: string;
readonly createdAt: Date;
readonly updatedAt: Date;
// #region Methods
myMethod(name: string): Promise<void>; // <<<===
// #endregion
}
interface ProjectCreationAttributes extends Omit< // <<<===
Optional<
ProjectAttributes,
| 'id'
| 'createdAt'
>,
'myMethod' // <<<===
> {}
class Project extends Model<ProjectAttributes, ProjectCreationAttributes>
implements ProjectAttributes {
public id: ProjectAttributes['id'];
public ownerId: ProjectAttributes['ownerId'];
public name: ProjectAttributes['name'];
public readonly createdAt: ProjectAttributes['createdAt'];
public readonly updatedAt: ProjectAttributes['updatedAt'];
public readonly myMethod: ProjectAttributes['myMethod'] // <<<===
/**
* Initialization to fix Sequelize Issue #11675.
*
* @see https://stackoverflow.com/questions/66515762/configuring-babel-typescript-for-sequelize-orm-causes-undefined-properties
* @see https://github.com/sequelize/sequelize/issues/11675
* @ref #SEQUELIZE-11675
*/
constructor(values?: TCreationAttributes, options?: BuildOptions) {
super(values, options);
// All fields should be here!
this.id = this.getDataValue('id');
this.ownerId = this.getDataValue('ownerId');
this.name = this.getDataValue('name');
this.createdAt = this.getDataValue('createdAt');
this.updatedAt = this.getDataValue('updatedAt');
this.myMethod = async (name) => { // <<<===
// Implementation example!
await this.update({
name,
});
};
}
// #region Methods
public toString() {
return `@${this.name} [${this.ownerId}] #${this.id}`;
}
// #endregion
}
Project.init(
{
id: {
type: DataTypes.INTEGER.UNSIGNED,
autoIncrement: true,
primaryKey: true,
},
ownerId: {
type: DataTypes.INTEGER.UNSIGNED,
allowNull: false,
},
name: {
type: new DataTypes.STRING(128),
allowNull: false,
},
myMethod: { // <<<===
type: DataTypes.VIRTUAL(DataTypes.ABSTRACT),
}
},
{
sequelize,
tableName: "projects",
}
);
