hoangvvo / next-connect

The TypeScript-ready, minimal router and middleware layer for Next.js, Micro, Vercel, or Node.js http/http2
https://www.npmjs.com/package/next-connect
MIT License
1.62k stars 65 forks source link

TypeScript: Body prop doesn't extend #153

Closed Nautman closed 2 years ago

Nautman commented 2 years ago

Hi,

I'm trying to extend the body prop in the Request. I have followed the following advice from the README (see below).

interface ExtendedRequest {
  user: string;
}
interface ExtendedResponse {
  cookie(name: string, value: string): void;
}

handler.post<ExtendedRequest, ExtendedResponse>((req, res) => {
  req.user = "Anakin";
  res.cookie("sid", "8108");
});

My problem is that I want to extend the body prop, like below. Unfortunately the name is typed as any instead of string.

interface ExtendedRequest {
  body: {
    name: string;
  }
}

handler.post<ExtendedRequest>((req, res) => {
  const name  = req.body.name;
  res.send(name);
});

Do you know how I can solve this? Thank you!

hoangvvo commented 2 years ago

Do you use NextAPIRequest as the base type? NextAPIRequest has its body type as any so anything that get merged into it is still any.

Nautman commented 2 years ago

You helped me solve it! I will close this issue. Thank you!

I needed to type the handler, i.e. use

interface RequestBody {
  body: { name: string };
}

const handler = nc<
  Omit<NextApiRequest, "body"> & RequestBody,
  NextApiResponse
>();

I've paste my full example here

// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type { NextApiRequest, NextApiResponse } from "next";
import nc from "next-connect";

interface RequestBody {
  body: { name: string };
}

const handler = nc<
  Omit<NextApiRequest, "body"> & RequestBody,
  NextApiResponse
>();

export default handler.post((req, res) => {
  const name = req.body.name;
  res.json({ msg: "hello world" });
});

When I was using this alongside with next-joi I had to type the post request as well. I've pasted that example below as well

// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import Joi from "joi";
import validate from "lib/middlewares/validation";
import type { NextApiRequest, NextApiResponse } from "next";
import nc from "next-connect";

const postSchema = Joi.object({
  name: Joi.string().required(),
});

const getSchema = Joi.object({
  id: Joi.string().required(),
});

interface PostRequestBody {
  body: { name: string };
}

interface GetRequestQuery {
  query: {
    id: string;
  };
}

type ExtendedRequest = Omit<NextApiRequest, "body"> & PostRequestBody;

const handler = nc<ExtendedRequest, NextApiResponse>();

export default handler
  .post<PostRequestBody>(validate({ body: postSchema }), (req, res) => {
    res.json({ msg: "hello world" });
  })
  .get<GetRequestQuery>(validate({ query: getSchema }), (req, res) => {
    res.json({ msg: "hello world" });
  });