Problem
One of the primary reasons I like using TypeScript is to check that I am passing correctly typed params to given function calls.
However, when using Next.js, I am running into the issue where params passed to a Next.js API endpoint end up losing their types when the are "demoted" to the NextApiRequest
type.
Typically, I would pull off params doing something like req.body.[param_name]
but that entire chain has type any
so I lose any meaningful type information.
Example
Let's assume I have an API endpoint in a Next.js project at pages/api/add.ts
which is responsible for adding two numbers. In this file, we also have a typed function for adding two numbers, that the API endpoint will call.
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!" });
}
};
The problem I am running into, and what I would like help with, is how to type req.body.number_one
and req.body.number_two
or any sort of param coming off of the request object. Is this possible?
Since the types off of the request object are any
TypeScript does not complain, even if you try calling the API endpoint with incorrectly typed params.
fetch("/api/add", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ number_one: 1, number_two: "two" }),
});
The TypeScript compiler will have no problems with the above call to the API endpoint, even though the types are incorrect. It treats the body
as an any
type, so it loses any type information.
It would be great if I could type params cast from the request body being sent to API endpoints in Next.js
CodePudding user response:
You can create a new interface that extends NextApiRequest
and adds the typings for the two fields.
interface ExtendedNextApiRequest extends NextApiRequest {
body: {
number_one: number;
number_two: number;
};
}
Then use it to type the req
object in the handler function.
export default async (req: ExtendedNextApiRequest, res: NextApiResponse) => {
//...
};