问题
我喜欢使用TypeScript的主要原因之一是检查是否向给定的函数调用传递了类型正确的参数。
但是,在使用Next.js时,我遇到了这样一个问题:传递给Next.js API端点的参数在被"降级"为NextApiRequest
类型时最终会丢失它们的类型。
通常,我会使用类似req.body.[param_name]
的参数,但整个链的类型为any
,因此我丢失了任何有意义的类型信息。
示例
让我们假设我在pages/api/add.ts
的Next.js项目中有一个API端点,负责两个数的相加,在这个文件中,我们还有一个类型化函数,用于两个数的相加,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_one
和req.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端点的请求主体转换而来的参数,那就太好了
8条答案
按热度按时间bn31dyow1#
您可以创建一个新接口,扩展
NextApiRequest
并添加两个字段的类型。然后使用它在处理函数中键入
req
对象。虽然扩展
NextApiRequest
类型将阻止TypeScript抱怨,但它不能防止潜在的运行时错误发生。要想找到一种更好的、类型安全的方法来缩小类型范围,请查看@Matthieu Gellé的答案。
e4eetjau2#
胡利奥的回答很有效,但官方文件并不鼓励这样做:
使用TypeScript扩展req/res对象
我还没有修改你的代码,使您可以很容易地集成它,如果你有勇气来修改这个砖尽管事实上,它“工程”
ujv3wf0j3#
只要做一个Type Guard并在你的处理程序中使用它。Matthieu的答案很棒,但是当有很多期望的属性时就很糟糕了。
当你发现自己要处理5个以上的属性时,检查通过主体发送的东西是否是某种类型的东西可能会花费相当多的时间。如果这些属性是嵌套的多层,那就更麻烦了。只要使用合适的验证器并为它们编写模式就行了。
为此,正如Matthieu所指出的,不应该通过覆盖现有属性来扩展
NextApiRequest
和NextApiResponse
,而应该扩展它们以添加其他属性。相反,我会编写一个泛型,如下所示:
并像这样使用它:
vql8enpb4#
注:我是Remult的维护者之一
如果可以接受另一种依赖关系,那么使用Remult时,可以对所有API调用使用类型安全代码(CRUD用于TypeScript模型,RPC用于函数)。
add
函数如下所示:你可以在前端导入它并直接调用它
Remult将发送
POST
请求,在Next.js API路由上处理它,并将值传递给后端的add
函数。如果您想进一步了解,可以使用Next.js tutorial。
yrwegjxp5#
虽然有点晚了,但是我在请求查询参数方面遇到了类似的问题。我已经解决了这个问题,并且我相信它仍然是类型安全的。只是在 intended available参数中添加了一些自动完成和代码级文档:https://github.com/vercel/next.js/discussions/36373
应易于修改,以支持身体以及
mutmk8jj6#
这里的挑战是,您既需要一个解决方案来确保类型安全,又需要对数据进行运行时验证。正如@dvlden所指出的,使用类型保护将提供这两种功能,这是实现这一目标的常见做法。然而,在更复杂的场景中,它可能会相当麻烦。
另一个可以帮助OP的dilema的工具是Zod, a TypeScript-first schema validation library,它可以确保你的数据具有正确的形状,如果是这样,也提供正确的类型。
我过去使用过Elm,Zod的方法与Elm的非常相似,对于每个HTTP请求,您必须提供一个类型正确的JSON decoder that parses the input data值,如果不能成功,则返回一个错误。我提到这一点是因为我认为Elm的实现在简单性和安全性方面是一个标准。
zzzyeukh7#
我认为我们可以在使用前使用express-validator验证主体。
然后,可以从使用TypeScript扩展req/res对象中使用一个简单的方法
wwtsj6pe8#
也有这个问题!最后定义了body对象,并将其传递到fetch中,其中包含一个接口,用于API中的req body
在你的例子中--
还有你所谓的“取”
最后为我工作了,当我没有所有想要的参数时, typescript 抛出了一个错误。希望这能有所帮助!