4
votes

Création de méthodes d'instance dans un modèle Sequelize à l'aide de Typescript

Je souhaite étendre une classe Sequelize Model pour ajouter d'autres méthodes d'instance, mais le typographie continue de se plaindre que "La propriété 'prototype' n'existe pas sur le type 'Model'"

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;
};

J'attends User.prototype.verifyUser pour fonctionner mais dactylographié se plaint. Comment ajouter aux typages?


0 commentaires

3 Réponses :


1
votes

Une solution que j'ai vue est où vous forcez le type après avoir déclaré le modèle. Donc

interface UserModelInstanceMethods extends Sequelize.Model<Instance, Attributes> {
  prototype: {
    verifyPassword: (password: string) => Promise<boolean>;
  };
}

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;
} as Sequelize.Model<Instance, Attributes> & UserModelInstanceMethods;


0 commentaires

3
votes

Suite au commentaire de @Shadrech, j'ai une alternative (moins hacky et abstraite).

sequelize.query("SELECT ...").then((user: UserInstance & UserModelInstanceMethods) => {
  user.verifyPassword(req.body.password) // <= from UserModelInstanceMethods
  user.getDataValue('name') // <= from UserInstance
})

Utilisation de votre modèle:

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;
}


0 commentaires

0
votes

Étape 1:

Définissez un nouveau type qui décrira la définition du modèle DefinedModel . De plus, recevez un T générique pour obtenir les réponses de la base de données définie par une interface.

Étape 2:

Créez une instance du modèle analysant le connection.define retour à notre DefinedModel.

// Step 0: Declarations
const connection: Sequelize = new Sequelize({...});
const modelName: string = '...';
const definition: ModelAttributes = {...};
const options: ModelOptions = {...};
interface MyInterface {...}; // Should describe table data

// Step 1
type DefinedModel<T> = typeof Model & {
  new(values?: object, options?: BuildOptions): T;
}

// Step 2
const model: DefinedModel<Model> = <DefinedModel<Model>>connection.define(modelName, definition, options);

// Step 2 with Interface definition
const iModel: DefinedModel<MyInterface & Model> = <DefinedModel<MyInterface & Model>> connection.define(modelName, definition, options);


0 commentaires