如何在Next.js中为NextApiRequest的body设置强类型以获得类型安全
Next.js 12 API路由请求Body类型安全实现方案
第一步:扩展支持泛型的NextApiRequest类型
Next.js 12 原生提供的NextApiRequest默认不支持泛型传入,我们可以通过接口继承的方式自定义扩展类型,支持传入query、body的泛型定义:
import type { NextApiRequest } from 'next'; // TQuery为请求query参数类型,TBody为请求body类型 export interface NextApiRequestExtend<TQuery = {}, TBody = any> extends NextApiRequest { query: TQuery; body: TBody; }
第二步:添加运行时参数校验
TypeScript的类型校验仅在编译阶段生效,要实现真正的类型安全,必须添加运行时的参数格式校验,你可以通过自定义类型守卫实现:
import { NextApiResponse } from "next"; import type { NextApiRequestExtend } from './你存放扩展类型的文件路径'; // 定义Body的类型 interface IBody { test: string; value: number; } // 类型守卫函数,运行时校验入参是否符合IBody格式 function isIBody(body: unknown): body is IBody { return ( typeof body === 'object' && body !== null && typeof (body as IBody).test === 'string' && typeof (body as IBody).value === 'number' ); } const handler = async ( req: NextApiRequestExtend<{}, IBody>, // 直接指定body的类型为IBody res: NextApiResponse ): Promise<void> => { // 先校验请求方法 if (req.method !== 'POST') { return res.status(405).json({ error: '仅支持POST请求' }); } // 运行时校验body格式 if (!isIBody(req.body)) { return res.status(400).json({ error: '请求参数格式错误' }); } // 此处req.body会被TypeScript自动推断为IBody类型,无需as强制转换,完全类型安全 const { test, value } = req.body; console.log(test, value); res.status(200).json({ text: "Hello" }); }; export default handler;
可选简化方案:使用Schema校验库
如果你的接口参数较多,手写类型守卫效率较低,可以使用zod、yup这类Schema校验库简化实现,以zod为例:
import { z } from 'zod'; // 定义Body的Schema const BodySchema = z.object({ test: z.string(), value: z.number() }); // 在handler中校验 try { const body = BodySchema.parse(req.body); // 此处body自动获得类型,无需额外定义interface } catch (e) { return res.status(400).json({ error: '参数格式错误' }); }
内容的提问来源于stack exchange,提问作者Jerome
相关产品推荐
相关产品推荐

