在Next.js+MongoDB的TS API中使用ObjectId出现类型错误
解决Next.js + MongoDB TypeScript API路由的类型错误
错误原因
Next.js的NextApiRequest.query里的参数类型被定义为string | string[] | undefined——因为URL允许重复同一个query参数(比如?postId=123&postId=456),所以TypeScript会认为参数可能是字符串数组。但MongoDB的ObjectId构造函数只接受单个字符串/数字等类型,不支持数组,所以出现类型不匹配的报错。
你之前设置默认值的方式没用,是因为默认值只处理了postId为undefined的情况,没覆盖它是数组的场景,类型依然包含string[]。
解决方案
要解决这个问题,需要先在运行时校验参数,同时缩小TypeScript的类型范围,确保传给ObjectId的是单个有效字符串:
修改你的GET路由代码如下:
.get(async (_req: NextApiRequest, res: NextApiResponse) => { const client = await clientPromise; const db = client.db(process.env.MONGO_DB); try { const { postId } = _req.query; // 1. 校验postId的有效性:不能是undefined,也不能是数组 if (!postId || Array.isArray(postId)) { return res.status(400).json({ message: "请提供有效的文章ID" }); } // 2. 此时TypeScript会自动推断postId是string类型,不再报错 const _id = new ObjectId(postId); const result = await db.collection("posts").findOne({ _id }); if (!result) { return res.status(404).json({ message: "未找到该文章" }); } res.json(result); } catch (error) { console.log("查询错误", error); res.status(500).json({ message: "服务器内部错误", }); } })
额外说明
- 必须加运行时校验:TypeScript的类型检查只在编译阶段生效,运行时如果用户传入重复的
postId参数,还是会变成数组,所以要主动判断并返回错误。 - 如果去掉
new ObjectId,查询不到结果是因为MongoDB存储的_id是ObjectId类型,直接用字符串查询的话,相当于找_id等于字符串的文档,和实际存储的ObjectId不匹配,所以必须转换类型。
内容的提问来源于stack exchange,提问作者program_bumble_bee
相关产品推荐
相关产品推荐

