Fedoranimus
Fedoranimus

Reputation: 826

Chaining ES6 Promises in Mongoose with Typescript

I'm attempting to chain ES6 promises with Mongoose 4.5.4

public static signup(req: express.Request, res: express.Response) {
    UserModel.findOne({ email: req.body.email }).exec()
    .then(existingUser => {
        if(existingUser) {
            return res.send({ message: 'Email is in use' });
        }

        return UserModel.create({
            firstName: req.body.firstName,
            lastName: req.body.lastName,
            email: req.body.email,
            password: req.body.password
        });
    })
    .then(user => {
            return res.send({ token: AuthUtils.createJWT(user)});
    })
    .catch(err => {
        console.log(err);
    });
}

However, Typescript is throwing the following error when I attempt to return UserModel.create(...):

Argument of type '(existingUser: IUser & _Model<IUser> & EventEmitter) => Response | MongoosePromise<IUser & _Model...' is not assignable to parameter of type '(...args: (IUser & _Model<IUser> & EventEmitter)[]) => void | (IUser & _Model<IUser> & EventEmitt...'. Type 'Response | MongoosePromise<IUser & _Model<IUser> & EventEmitter>' is not assignable to type 'void | (IUser & _Model<IUser> & EventEmitter) | PromiseLike<IUser & _Model<IUser> & EventEmitter>'. Type 'Response' is not assignable to type 'void | (IUser & _Model<IUser> & EventEmitter) | PromiseLike<IUser & _Model<IUser> & EventEmitter>'. Type 'Response' is not assignable to type 'PromiseLike<IUser & _Model<IUser> & EventEmitter>'. Property 'then' is missing in type 'Response'.

.create() returns a Promise, so I cannot see how this would be an issue.

Any help would be appreciated.

Upvotes: 3

Views: 1018

Answers (2)

Fedoranimus
Fedoranimus

Reputation: 826

I actually ended up building my project for ES6 so that I could use async/await

It allowed me to simplify the code drastically.

public static async signup(req: express.Request, res: express.Response) {
    try {
        let user = await UserModel.findOne({ email: req.body.email }).exec()
        if(user) {
            throw `Email ${user.email} is in use`;
        }
        if(environment.debug) console.log(`Creating new user ${req.body.firstName} ${req.body.lastName} with email ${req.body.email}`);
        user = await UserModel.create({
            firstName: req.body.firstName,
            lastName: req.body.lastName,
            email: req.body.email,
            password: req.body.password
        });
        return res.send({ token: AuthUtils.createJWT(user)});
    } catch(e) {
        console.log(e);
        res.send({ error: e });
    }
}

Upvotes: 1

Juan Stiza
Juan Stiza

Reputation: 523

Add control flow to the existing user by using a existing flag on the promise's response. Example:

public static signup(req: express.Request, res: express.Response) {
      UserModel.findOne({ email: req.body.email }).exec()
      .then(existingUser => {
          if(existingUser) {
              return Promise.resolve({
                user: existing,
                existing: true
              });
          }
          return UserModel.create({
              firstName: req.body.firstName,
              lastName: req.body.lastName,
              email: req.body.email,
              password: req.body.password
          }).then((user) => {
            return Promise.resolve({
              existing: false,
              user: user
            });
          });
      })
      .then(response => {
        if (response.existing) {
          return res.send({ message: `Email ${response.user.email} is in use` });
        } else return res.send({ token: AuthUtils.createJWT(response.user)});
      })
      .catch(err => {
          console.log(err);
      });
  }

Upvotes: 4

Related Questions