Home > Software design >  How to add TypeScript types to request body in Next.js API route?
How to add TypeScript types to request body in Next.js API route?

Time:11-10

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) => {
    //...
};
  • Related