Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
677 views
in Technique[技术] by (71.8m points)

node.js - mongoose property 'password' does not exist on type 'Document<any>

-- userSchema.ts interface

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

export interface UserDoc extends Document {
  name: {
    type: string;
    required: boolean;
  };
  email: {
    type: string;
    required: boolean;
  };
  password: {
    type: string;
    required: boolean;
  };
  dateJoined: {
    type: string;
    default: string;
  };
}

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

  dateJoined: {
    type: String,
    default: moment().format("MMMM Do YYYY"),
  },
});

I created my user model and the problem I'm having is creating the matchPassword method with uses bcrypt to compare the enteredPassword parameter vs the password from the Database

userSchema.methods.matchPassword = async function (enteredPassword) {
  return await bcrypt.compare(enteredPassword, this.password); ***
};

userSchema.pre("save", async function (next) {
  if (this.isModified("password")) {
    next();
  }

  const salt = bcrypt.genSalt(10);

  *** this.password = await bcrypt.hash(this.password, await salt); ***
});

const User = mongoose.model("User", userSchema);

The error message is as follows:

Property 'password' does not exist on type 'Document<any>'.

and this error is on each instance of this.password highlighted by the ***

I have used this same method before in Javascript so I do not know why It doesn't work on typescript and how can I bind the this.password to the Mongoose Document

Thank you

question from:https://stackoverflow.com/questions/66052916/mongoose-property-password-does-not-exist-on-type-documentany

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It looks like @Mohammad has helped you with the bcrypt implementation. I can help you with the typescript errors!

UserDoc is a typescript interface, so it shouldn't have fields like required. It should just describe the type of a UserDoc object. Properties are required by default. We use ?: if they are optional, but it looks like all are required here.

export interface UserDoc extends Document {
  name: string;
  email: string;
  password: string;
  dateJoined: string;
  matchPassword: (pw: string) => Promise<boolean>
}

When you create userSchema, you tell typescript that this is the schema for a UserDoc - not just any Document - by setting the generic variable of the Schema constructor to UserDoc.

const userSchema = new Schema<UserDoc>({ ...

This clears up the errors in userSchema.methods.matchPassword since we know that this.password is a string. We also know that enteredPassword is a string because we defined the args for this matchPassword method in the UserDoc interface.

For some reason, the pre method doesn't know our document type automatically. But the pre method is itself a generic function, so we can specific again that our doc is a UserDoc.

userSchema.pre<UserDoc>( ...

This is dumb but we have to specify the generic again when we create the model.

const User = mongoose.model<UserDoc>("User", userSchema);

Now User has type mongoose.Model<UserDoc, {}> and any methods that you call should return a UserDoc instead of just a Document.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...