【问题标题】:How to return a mongoose document from a function using typescript如何使用打字稿从函数返回猫鼬文档
【发布时间】:2021-09-26 22:35:55
【问题描述】:

我有两条路由对令牌执行相同的操作以从数据库中提取用户文档。之后,两者都对该文档执行不同的操作。为了改进代码,我试图将相同的操作部分放在一个函数中并在两个路由中调用它。有点像 -

    let user = await returnUser(req, res, token)
    user.verified = true;
    await user.save();

但问题是我正在使用 Typescript,并且在执行 user.save() 之类的操作或访问文档中的项目时遇到类型错误。谁能告诉我如何设置类型,以便我可以访问从函数返回的文档而不会出现类型错误。

编辑:我正在添加代码。 将返回文档的函数 -

import { Request, Response } from "express";
import { Token } from "../util/token";
import { User } from "../models/user";

export const returnUser = async (
  req: Request,
  res: Response,
  token: string
) => {
  if (!token) return res.status(400).send({ error: "Token is not present" });

  let decoded = await Token.decode(token);

  if (decoded === false) {
    return res.status(400).send({ error: "Invalid Token" });
  }

  let email = decoded.email;
  let user = await User.findOne({ email });

  if (!user) return res.status(400).send({ error: "User not found" });
  if (user.createdAt.getTime() !== decoded.epoch)
    return res.status(400).send({ error: "Invalid timestamp" });

  return user;
};

还有错误-

Message when hovering over the error

我的用户文档 -

interface UserDoc extends mongoose.Document {
  email: string;
  username: string | null;
  verified: boolean;
  createdAt: Date;
}

【问题讨论】:

  • 请添加更多你的实现,以便我们看到你想要改进的地方
  • 确切的错误会很好
  • @AshwynHorton 添加了代码。
  • @AutMai 也添加了错误。
  • 太棒了,谢谢

标签: typescript express mongoose


【解决方案1】:

我不知道这是否是解决方案,但我认为您在 findOne 语句中犯了一个错误:

你做到了:

User.findOne({ email });


但是你应该确保你传递了一个字段名和一个它应该匹配的值:

User.findOne ({ "email" : email });

有效,如果您的字段名称是电子邮件(查看您的模型)。

【讨论】:

    【解决方案2】:

    问题的原因是您返回response.send(),它没有UserDoc 类型,但据我所知,您的模型是正确的。我看不到您的Schema 的代码,但无论如何我们都会解决它。那么让我们开始吧:

    1. 让我们首先考虑Schema
    // a schema definition does accept a generic reference when instantiating it.
    // this also adds better typings with mongoose
    export const UserDocSchema = new mongoose.Schema<UserDoc>({/* model */});
    
    1. 现在让我们看看提供的实现。该错误是由函数中返回的响应调用引起的,因此将在函数上定义显式返回类型。使函数返回此类型将在您返回 res.send() 调用时出现类型错误...
    import { Request, Response } from "express";
    import { Token } from "../util/token";
    import { User } from "../models/user";
    
    // so to stop the return errors we will instead of return send responses
    // we will take advantage of the error handling situation which will fix
    // the typing dilemma...
    export const returnUser = async (token: string): Promise<UserDoc> => {
      if (!token) throw Error("Token is not present");
    
      let decoded = await Token.decode(token);
      if (decoded === false) {
        throw Error("Invalid Token");
      }
    
      let email = decoded.email;
      let user = await User.findOne({ email });
    
      if (!user) throw Error("User not found");
      if (user.createdAt.getTime() !== decoded.epoch)
        throw Error("Invalid timestamp");
    
      return user;
    };
    
    1. 所以现在使用函数的方式,我们将调用您的函数 所以根据您提供的屏幕截图...
    router.post('user/verify', (request, response) => {
      const { token } = request.body;
    
      return returnUser(token)
      .then((user) => {
        // this way this function is guaranteed to return a user
        return response.status(200).send(user.toObject());
      })
      .catchError((error) => {
        return response.status(400).send({ error: error.message });
      });
    });
    
    

    更新:

    要导入 UserDoc,您必须在此处导出它,

    export interface UserDoc extends mongoose.Document {
      email: string;
      username: string | null;
      verified: boolean;
      createdAt: Date;
    }
    

    我还没有机会对此进行测试,但我认为它应该可以解释为什么您的函数调用会提出打字错误建议...希望这能解决

    【讨论】:

    • 如何导入 UserDoc> 在用户模型文件中,我只导出这个 - const User = mongoose.model("User", userSchema);导出{用户};我要导出 { User, UserDoc }
    • 哦,我明白了,只需在问题陈述中的接口定义后面添加export
    • 嘿伙计。谢谢你的详细回答。这对我帮助很大。我现在已经实施了该解决方案,它正在按我的预期工作。我附上了代码的链接。我遵循了您所展示的内容,但没有使用 throw Error,因为我还没有设置错误处理程序。谢谢你,兄弟。 pastebin.com/082ks3q8
    • 太好了,我检查了你那里的解决方案。快速提示,您有调用send 函数两次的风险,这将导致运行时错误,因为您只能响应一次。
    • 我应该使用 return null 选项吗?
    猜你喜欢
    • 2018-08-20
    • 2018-04-22
    • 2021-08-04
    • 2016-02-05
    • 2020-05-11
    • 1970-01-01
    • 2017-01-23
    • 2019-10-06
    • 2020-10-29
    相关资源
    最近更新 更多