簡體   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