[英]Create mongoose schema methods using TypeScript
I try to create method hashPassword for user schema.我尝试为用户模式创建方法 hashPassword。
schema.method("hashPassword", function (): void {
const salt = bcrypt.genSaltSync(10);
const hash = bcrypt.hashSync(this.password, salt);
this.password = hash;
});
And get an error Property 'password' does not exist on type 'Document<any>'.
并得到一个错误Property 'password' does not exist on type 'Document<any>'.
on password关于密码
Here is my file这是我的文件
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");
At the point where you define the method, the schema
object doesn't know that it is the Schema
for an IUser
and not just any Document
.在定义方法时, schema
object 不知道它是IUser
的Schema
而不仅仅是任何Document
。 You need to set the generic type for the Schema
when you create it: new Schema<IUser>(... )
.创建Schema
时需要为它设置泛型类型: new Schema<IUser>(... )
。
You should declare an interface that extends Model like so:您应该声明一个扩展 Model 的接口,如下所示:
interface IUser {...}
interface IUserInstanceCreation extends Model<IUser> {}
then declare your schema;然后声明你的模式;
const userSchema = new Schema<IUser, IUserInstanceCreation, IUser>({...})
This would as well ensure that the Schema follows the attributes in IUser.这也将确保 Schema 遵循 IUser 中的属性。
As suggested by one of the collaborators of mongoose, we can use the below way for creating instance methods:正如 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
link: https://github.com/Automattic/mongoose/issues/10358#issuecomment-861779692链接: https://github.com/Automattic/mongoose/issues/10358#issuecomment-861779692
This makes is Clear Enough这很清楚
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;
Solution to avoid having to redefine types that are already in the schema避免必须重新定义模式中已经存在的类型的解决方案
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.