如何在Next.js中为NextApiRequest添加自定义类型?

d8tt03nd  于 2023-05-06  发布在  其他
关注(0)|答案(1)|浏览(129)

我有一个中间件,可以检查发出请求的用户是否有一个有效的JWT令牌来请求Next.js中的API。我使用TypeScript编写了这个中间件,但我得到了一个类型错误。
我的代码如下:

import { verifyJwtToken } from "../utils/verifyJwtToken.js";
import { NextApiHandler, NextApiRequest, NextApiResponse } from 'next'
import cookie from "cookie"

const authMiddleware = (handler: NextApiHandler) => async (req: NextApiRequest, res: NextApiResponse) => {
  try {
    
 
    const cookies = cookie.parse(req.headers.cookie || '')
    const token = cookies.token
    const verifiedToken = await verifyJwtToken(token)

    if (!verifiedToken) {
      throw new Error('You have no access to do it.')
    }
    
    const userId = Number(verifiedToken.id)

    // Call the API route handler with the updated request object
    return handler({ ...req, userId }, res)
  } catch (err) {
    console.error(err)
    res.status(401).json({ message: 'You have no access to do it.' })
  }
}

export default authMiddleware;

错误如下:

Argument of type '{ userId: number; query: Partial<{ [key: string]: string | string[]; }>; cookies: Partial<{ [key: string]: string; }>; body: any; env: Env; preview?: boolean | undefined; ... 35 more ...; eventNames(): (string | symbol)[]; }' is not assignable to parameter of type 'NextApiRequest'.

Object literal may only specify known properties, and 'userId' does not exist in type 'NextApiRequest'.ts(2345)

为了修复这个错误,我创建了一个扩展NextApiRequest并包含userId属性的自定义接口。下面是一个例子:

import { NextApiRequest } from 'next'

interface CustomNextApiRequest extends NextApiRequest {
  userId: number
}

export default CustomNextApiRequest;

然后,我尝试使用这个自定义接口作为中间件函数中req参数的类型,如下所示:

import CustomNextApiRequest from './CustomNextApiRequest';

const authMiddleware = (handler: NextApiHandler) => async (req: CustomNextApiRequest, res: NextApiResponse) => {
  // ...
}

但没有用。
顺便说一句,这个代码工作。但我想修复这个类型错误。

xjreopfe

xjreopfe1#

您的CustomNextApiRequest声明是正确的。问题在于你的中间件是如何链接在一起的。我建议你有一个CustomNextApiHandler,如下所示(随意调整返回类型):

interface CustomNextApiRequest extends NextApiRequest {
  userId: number;
}
export type CustomNextApiHandler = (req: CustomNextApiRequest, res: NextApiResponse) => void;

您的addCommentHandler将使用上面的CustomNextApiHandler类型:

export const addCommentHandler: CustomNextApiHandler = (req, res) => {};

最后,您的authMiddleware将如下所示(注意新注解):

const authMiddleware =
  (handler: CustomNextApiHandler) => async (req: CustomNextApiRequest, res: NextApiResponse) => {
    try {
      const cookies = cookie.parse(req.headers.cookie || "");
      const token = cookies.token;
      const verifiedToken = await verifyJwtToken(token);

      if (!verifiedToken) {
        throw new Error("You have no access to do it.");
      }
      const userId = Number(verifiedToken.id);
      // Added it like this instead of destructuring it
      req.userId = userId;
      // Call the API route handler with the updated request object
      return handler(req, res);
    } catch (err) {
      console.error(err);
      res.status(401).json({ message: "You have no access to do it." });
    }
  };

相关问题