无法访问Typescript中的mongoose Schema上下文

时间:2016-07-24 16:54:22

标签: node.js mongodb typescript mongoose

我正在尝试将.pre.method.static函数应用于我的Mongoose模式。

我有以下代码,但我的this要么处于错误的上下文中,要么我误解了Schemas。

export interface IUser extends mongoose.Document {
    email: string;
    password: string;
    firstName: string;
    lastName: string;
    comparePassword(password: string, callback: Function): void;
}

class UserSchema {
    static get schema(): mongoose.Schema {
        let userSchema = new mongoose.Schema({
            email: {
                type: String,
                unique: true,
                lowercase: true
            },
            firstName: {
                type: String,
                required: true
            },
            lastName: {
                type: String,
                required: true
            },
            password: {
                type: String,
                select: false
            }
        });

        userSchema.pre('save', this.saveHandler);        
        userSchema.method('comparePassword', this.comparePassword);

        return userSchema;
    }

    static saveHandler(next) {
        let user = this.schema;
        if(!user.isModified('password')) {
              return next();
         }
          bcrypt.genSalt(10, (err, salt) => {
              bcrypt.hash(user.password, salt, (err, hash) => {
                  user.password = hash;
                  next();
              });
          });
    }

    static comparePassword(password: string, callback: Function) {
        let user = this.schema;
        bcrypt.compare(password, user.password, (err, isMatch) => {
            callback(err, isMatch);
        });
    }
}

export const UserModel = mongoose.model<IUser>('User', UserSchema.schema);

Typescript会抛出Property 'isModified' does not exist on type 'Schema'.

的错误

然而,在javascript:

var schema = new Schema({
    email: { type: String, unique: true, lowercase: true },
    password: { type: String, select: false },
    firstName: String,
    lastName: String,
});

schema.pre('save', function(next) {
    var user = this;
    if(!user.isModified('password')) {
        return next();
    }
    bcrypt.genSalt(10, function(err, salt) {
        bcrypt.hash(user.password, salt, function(err, hash) {
            user.password = hash;
            next();
        });
    });
});

确实有正确的this上下文。如何正确构建我的Typescript代码以产生相同的效果?

2 个答案:

答案 0 :(得分:0)

这里的问题是静态方法中的这个值。这是您的原始代码。

class UserSchema {
    static get schema(): mongoose.Schema {
        let userSchema = new mongoose.Schema({ ... });
        // this does not refer to UserSchema!
        userSchema.pre('save', this.saveHandler); 
        userSchema.method('comparePassword', this.comparePassword);
        return userSchema;
    }

    static saveHandler(next) {
       ...
    }

    static comparePassword(password: string, callback: Function) {
       ...
    }
}

因此,第一种方法可能是使用this引用

更改UserSchema关键字
class UserSchema {

    static get schema(): mongoose.Schema {
        let userSchema = new mongoose.Schema({ ... })
        userSchema.pre('save', UserSchema.saveHandler);        
        userSchema.method('comparePassword', UserSchema.comparePassword);
        return userSchema;
    }

    static saveHandler(next) {
        let user = UserSchema.schema;
        ...
    }

    static comparePassword(password: string, callback: Function) {
        ...
    }
}

但是,正如@toskv所说,我建议不要使用静态方法。打字稿是Javascript的一大进步,但不像Java那样思考。使用基于模块的设计 例如,您可以将模块 userSchema.ts 定义为以下模板:

// private to the module
const _schema = new mongoose.Schema({ ... })
_schema.pre('save', _saveHandler)
_schema.method('comparePassword', _comparePassword)

/** from the outside you'll call it as 
 *
 *  const userSchema = require('...')
 *  userSchema.getSchema()
 */
export function getSchema() {
 return _schema
}

// private to the module
function _saveHandler(next: Function) {
  ...
}

// private to the module
function _comparePassword(next: Function) {
  ...
}

答案 1 :(得分:0)

使用没有箭头函数的函数就像 Fedoranimus 所说的那样