node.js - Sequelize-associationer - specialmetoder/mixins skapas inte?
Enligt dokumentationen: https://sequelize.org/docs/v6/core-concepts/assocs/#special-methodsmixins-added-to-instances
När en association definieras mellan två modeller får instanserna av dessa modeller speciella metoder för att interagera med sina associerade motsvarigheter.
Speciella metoder/mixins bör vara tillgängliga för användarinstansen, såsom user.addFriend(), user.removeFriend(), när det finns en tillämpad belongsToMany-, hasMany-association, men det finns ett problem.
import { Model, DataTypes, Optional } from "sequelize";
import sequelize from "../../sequelize";
import { UserAttributes } from "./user.def";
interface UserCreationAttributes extends Optional<UserAttributes, "userId"> { }
export class User
extends Model<UserAttributes, UserCreationAttributes>
implements UserAttributes {
public userId!: number;
public active!: boolean;
public firstName!: string;
public lastName!: string;
public username!: string;
}
const instance = User.init(
{
userId: {
field: "user_id",
type: DataTypes.BIGINT,
primaryKey: true,
autoIncrement: true,
},
active: {
field: "active",
type: DataTypes.BOOLEAN,
defaultValue: true,
allowNull: false,
},
firstName: {
field: "first_name",
type: DataTypes.STRING(100),
allowNull: false,
},
lastName: {
field: "last_name",
type: DataTypes.STRING(100),
allowNull: false,
},
username: {
field: "username",
type: DataTypes.STRING(),
allowNull: false,
unique: true,
},
},
{
sequelize,
tableName: "user",
freezeTableName: true,
}
);
User.belongsToMany(User, { foreignKey: 'friend_id', as: 'Friend', through: 'UserFriend' })
export { instance };
Dessa metoder är inte skapade. Förresten, 'through'-tabellen UserFriend är skapad i databasen.
Jag vet inte om det här problemet har något att göra med TypeScript, eller med sättet att skapa denna självrefererande association. Det första jag misstänker är problemet, är sättet att skapa dessa associationer, men jag har försökt alla möjligheter för att koppla modeller, och speciella metoder skapades aldrig.
Finns det något sätt för mig att kontrollera om dessa metoder är skapade, eftersom mitt IDE visar detta meddelande - Egenskapen 'addFriend' finns inte på typen 'User' (tydligt inte skapad). Om någon känner igen dessa typer av problem, eller var jag kan lära mig mer om detta ämne och dessa typer av problem, skulle jag vara mycket tacksam. Alla råd kommer att vara till hjälp.
Svar #1
Problemet är att dessa funktioner definieras vid körning medan TypeScript kommer att misslyckas om de inte deklareras vid kompilering, därför måste du själv deklarera deras signaturer i modellen, endast signaturen, implementeringen tas om hand av Sequelize själv. Eftersom du har en belongsToMany-relation kan du lägga till följande signaturer på följande sätt i modellklassen
export class User
extends Model<UserAttributes, UserCreationAttributes>
implements UserAttributes {
public userId!: number;
public active!: boolean;
public firstName!: string;
public lastName!: string;
public username!: string;
declare getFriends: BelongsToManyGetAssociationsMixin<User>;
declare addFriend: BelongsToManyAddAssociationsMixin<User, number>;
// etc...
}
se https://sequelize.org/docs/v6/other-topics/typescript/#usage
Svar #2
Jag har exakt samma problem just nu. Jag har ingen komplett lösning men jag har en del av den. Jag vill säga att denna kod innehåller någon typ av bugg, men hänvisar dig till de ofullständiga men ändå användbara dokumenten för att kombinera TypeScript med Sequelize för att försöka fixa buggen.
Jag vet inte vilka associationer du skulle göra i din kod, men för mig har jag en Profile-modell som kopplar till Account-modellen, Housing-modellen och Gym-modellen, så här:
export class Profile extends Model<ProfileAttributes, ProfileCreationAttributes> implements ProfileAttributes {
public profileId!: number;
public acctId!: ForeignKey<Account["acctId"]>;
public ipAddress!: string;
public readonly createdAt!: Date;
public readonly updatedAt!: Date;
public readonly deletedAt!: Date;
declare getAccount: BelongsToGetAssociationMixin<Account>;
declare setAccount: BelongsToSetAssociationMixin<Account, number>;
declare getHousings: HasManyGetAssociationsMixin<Housing>;
declare addHousing: HasManyAddAssociationMixin<Housing, number>;
declare addHousings: HasManyAddAssociationsMixin<Housing, number>;
declare getGyms: HasManyGetAssociationsMixin<Gym>;
declare addGym: HasManyAddAssociationMixin<Gym, number>;
declare addGyms: HasManyAddAssociationsMixin<Gym, number>;
public readonly Housings?: Housing[];
public readonly Gyms?: Gym[];
public static associations: {
Housings: Association<Profile, Housing>;
Gyms: Association<Profile, Gym>;
};
static initModel(sequelize: S): typeof Profile {
return Profile.init(
{
profileId: {
type: DataTypes.INTEGER,
unique: true,
autoIncrement: true,
primaryKey: true,
},
ipAddress: {
type: DataTypes.STRING,
allowNull: false,
},
},
{
timestamps: true,
sequelize: sequelize,
paranoid: false,
},
);
}
}
Och relationen mellan Profil, Konto, Boende och Gym är så här:
Account.hasOne(Profile, { foreignKey: "acctId", as: "profile" });
Profile.belongsTo(Account, { foreignKey: "acctId", as: "account" });
// https://sequelize.org/docs/v6/advanced-association-concepts/advanced-many-to-many/
Profile.belongsToMany(Housing, { through: "Profile_Housings", as: "housings" });
Housing.belongsToMany(Profile, { through: "Profile_Housings", as: "profile" });
Profile.belongsToMany(Gym, { through: "Profile_Gyms", as: "gyms" });
Gym.belongsToMany(Profile, { through: "Profile_Gyms", as: "profile" });
Profile.hasMany(Feedback, { foreignKey: "profileId", as: "their_feedback" });
Feedback.belongsTo(Profile, { foreignKey: "profileId", as: "feedback_from" });
Därför kan jag nu göra profile.getHousings(); och profile.addHousing(housing);
