【问题标题】:How to add TypeScript types to request body in Next.js API route?如何在 Next.js API 路由中添加 TypeScript 类型以请求正文?
【发布时间】:2021-12-21 21:03:10
【问题描述】:

问题

我喜欢使用 TypeScript 的主要原因之一是检查我是否将正确键入的参数传递给给定的函数调用。

但是,在使用 Next.js 时,我遇到了这样一个问题:传递给 Next.js API 端点的参数在被“降级”为 NextApiRequest 类型时最终会丢失它们的类型。

通常,我会执行类似req.body.[param_name] 的参数,但整个链的类型为any,因此我会丢失任何有意义的类型信息。

示例

假设我在 Next.js 项目中有一个 API 端点 pages/api/add.ts,它负责添加两个数字。在这个文件中,我们还有一个用于添加两个数字的类型函数,API 端点将调用该函数。

const add = (a: number, b: number): number => a + b;

export default async (req: NextApiRequest, res: NextApiResponse) => {
  try {
    const result = add(req.body.number_one, req.body.number_two);
    res.status(200).json(result);
  } catch (err) {
    res.status(403).json({ err: "Error!" });
  }
};

我遇到的问题以及我想要帮助的问题是如何键入req.body.number_onereq.body.number_two 或来自请求对象的任何类型的参数。这可能吗?

由于请求对象的类型是any,因此即使您尝试使用输入错误的参数调用 API 端点,TypeScript 也不会抱怨。

fetch("/api/add", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ number_one: 1, number_two: "two" }),
});

TypeScript 编译器对上述 API 端点的调用没有问题,即使类型不正确。它将body 视为any 类型,因此它会丢失任何类型信息。

如果我可以键入从请求正文中转换到 Next.js 中的 API 端点的参数,那就太好了

【问题讨论】:

    标签: typescript next.js


    【解决方案1】:

    julio 的回答有效,但官方文档不鼓励这样做:
    Extending the req/res objects with TypeScript

    const add = (a: number, b: number): number => a + b;
    
    export default async (req: NextApiRequest, res: NextApiResponse) => {
      const { body } = req;
      try {
        if (
          "number_one" in body &&
          typeof body.number_one === "number" &&
          "number_two" in body &&
          typeof body.number_two === "number"
        ) {
          const result = add(body.number_one, body.number_two);
          return res.status(200).json(result);
        }
        throw new Error("number_one or number_two is not a number");
      } catch (err) {
        return res.status(403).json({ err: "Error!" });
      }
    };
    

    我没有对你的代码进行太多修改,以便你可以轻松集成它,如果你有勇气来修改这个砖,尽管它“有效”

    【讨论】:

      【解决方案2】:

      您可以创建一个扩展 NextApiRequest 的新界面并添加两个字段的类型。

      interface ExtendedNextApiRequest extends NextApiRequest {
        body: {
          number_one: number;
          number_two: number;
        };
      }
      

      然后使用它在处理函数中键入req 对象。

      export default async (req: ExtendedNextApiRequest, res: NextApiResponse) => {
          //...
      };
      

      虽然扩展 NextApiRequest 类型会阻止 TypeScript 抱怨,但它并不能防止发生潜在的运行时错误。

      如需更好的类型安全方法来缩小类型范围,请查看@Matthieu Gellé's answer

      【讨论】:

        猜你喜欢
        • 2021-04-02
        • 2020-06-06
        • 1970-01-01
        • 2020-12-24
        • 2022-10-08
        • 2019-09-24
        • 2020-08-12
        • 2021-06-28
        • 2021-10-07
        相关资源
        最近更新 更多