繁体   English   中英

使用 TypeScript 创建 mongoose 模式方法

[英]Create mongoose schema methods using TypeScript

我尝试为用户模式创建方法 hashPassword。

schema.method("hashPassword", function (): void {
  const salt = bcrypt.genSaltSync(10);
  const hash = bcrypt.hashSync(this.password, salt);

  this.password = hash;
});

并得到一个错误Property 'password' does not exist on type 'Document<any>'. 关于密码

这是我的文件

import mongoose, { Schema, Document } from "mongoose";
import bcrypt from "bcryptjs";

/**
 * This interface should be the same as JWTPayload declared in types/global.d.ts file
 */
export interface IUser extends Document {
  name: string;
  email: string;
  username: string;
  password: string;
  confirmed: boolean;
  hashPassword: () => void;
  checkPassword: (password: string) => boolean;
}

// User schema
const schema = new Schema(
  {
    name: {
      type: String,
      required: true,
    },
    email: {
      type: String,
      required: true,
    },
    username: {
      type: String,
      required: true,
    },
    password: {
      type: String,
      required: true,
    },
    confirmed: {
      type: Boolean,
      default: false,
    },
  },
  { timestamps: true }
);

schema.method("hashPassword", function (): void {
  const salt = bcrypt.genSaltSync(10);
  const hash = bcrypt.hashSync(this.password, salt);

  this.password = hash;
});

// User model
export const User = mongoose.model<IUser>("User", schema, "users");

在定义方法时, schema object 不知道它是IUserSchema而不仅仅是任何Document 创建Schema时需要为它设置泛型类型: new Schema<IUser>(... )

您应该声明一个扩展 Model 的接口,如下所示:

    interface IUser {...}
    interface IUserInstanceCreation extends Model<IUser> {}

然后声明你的模式;

    const userSchema = new Schema<IUser, IUserInstanceCreation, IUser>({...})

这也将确保 Schema 遵循 IUser 中的属性。

正如 mongoose 的一位合作者所建议的,我们可以使用以下方式来创建实例方法:

const schema = new Schema<ITestModel, Model<ITestModel, {}, InstanceMethods>> // InstanceMethods would be the interface on which we would define the methods

schema.methods.methodName = function() {}

const Model = model<ITestModel, Model<ITestModel, {}, InstanceMethods>>("testModel", ModelSchema)

const modelInstance = new Model();
modelInstance.methodName() // works

链接: https://github.com/Automattic/mongoose/issues/10358#issuecomment-861779692

这很清楚

import mongoose, { Schema, Document, Model } from "mongoose";
import bcrypt from "bcrypt";

interface IUser {
    username: string;
    hashedPassword: string;
}

interface IUserDocument extends IUser, Document {
    setPassword: (password: string) => Promise<void>;
    checkPassword: (password: string) => Promise<boolean>;
}

interface IUserModel extends Model<IUserDocument> {
    findByUsername: (username: string) => Promise<IUserDocument>;
}

const UserSchema: Schema<IUserDocument> = new Schema({
    username: { type: String, required: true },
    hashedPassword: { type: String, required: true },
});

UserSchema.methods.setPassword = async function (password: string) {
    const hash = await bcrypt.hash(password, 10);
    this.hashedPassword = hash;
};

UserSchema.methods.checkPassword = async function (password: string) {
    const result = await bcrypt.compare(password, this.hashedPassword);
    return result;
};

UserSchema.statics.findByUsername = function (username: string) {
    return this.findOne({ username });
};

const User = mongoose.model<IUserDocument, IUserModel>("User", UserSchema);
export default User;

避免必须重新定义模式中已经存在的类型的解决方案

import { Schema, model, InferSchemaType } from "mongoose"
import bcrypt from "bcrypt"

const userSchema = new Schema({
    name: String,
    email: {
        type: String,
        required: true,
        unique: true
    },
    password: String,
})

userSchema.methods.verifyPassword = async function(password: string){
    return await bcrypt.compare(password, this.password)
}

declare interface IUser extends InferSchemaType<typeof userSchema> {
    verifyPassword(password: string): boolean
}

export const UserModel = model<IUser>("Users", userSchema)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM