You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

Next.js JWT验证中间件TypeScript类型错误修复

问题背景

我在Next.js中使用TypeScript开发了一个JWT验证中间件,用于校验API请求的用户是否持有有效JWT令牌。代码功能正常运行,但存在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)

    // 调用API路由处理器并传入添加了userId的请求对象
    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的自定义接口,试图通过修改中间件的req参数类型来解决问题,但并未生效:

// CustomNextApiRequest.ts
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) => {
  // ...原代码逻辑
}

中间件使用示例

async function addCommentHandler(req: NextApiRequest, res: NextApiResponse) {
  // 业务逻辑代码...
}
export default authMiddleware(addCommentHandler);

正确解决方案

问题根源在于:中间件接收的NextApiHandler仅支持标准NextApiRequest类型,但我们传入了带有自定义userId属性的请求对象。需要调整中间件的类型定义,让它兼容处理自定义请求的处理器,同时在调用时正确做类型断言。

步骤1:定义自定义请求接口

在项目中创建类型文件(比如types/CustomNextApiRequest.ts):

import { NextApiRequest } from 'next';

export interface CustomNextApiRequest extends NextApiRequest {
  userId: number;
}

步骤2:修改中间件的类型定义

调整中间件,使其接受处理CustomNextApiRequest的处理器,同时保持中间件本身对外暴露标准的NextApiHandler类型:

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

// 定义中间件类型:接收处理自定义请求的处理器,返回标准NextApiHandler
const authMiddleware = (handler: (req: CustomNextApiRequest, res: NextApiResponse) => Promise<void> | void): NextApiHandler => {
  return 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);

      // 使用类型断言将扩展后的请求对象转为CustomNextApiRequest
      return handler({ ...req, userId } as CustomNextApiRequest, res);
    } catch (err) {
      console.error(err);
      res.status(401).json({ message: 'You have no access to do it.' });
    }
  };
};

export default authMiddleware;

步骤3:更新业务处理器的请求类型

在使用中间件的API路由中,将处理器的req参数类型改为CustomNextApiRequest,这样就能获得userId的类型提示:

import { NextApiResponse } from 'next';
import { CustomNextApiRequest } from './types/CustomNextApiRequest';
import authMiddleware from './authMiddleware';

async function addCommentHandler(req: CustomNextApiRequest, res: NextApiResponse) {
  // 可以直接使用req.userId,且有类型提示
  console.log('当前用户ID:', req.userId);
  // 业务逻辑代码...
}

export default authMiddleware(addCommentHandler);

内容的提问来源于stack exchange,提问作者periakteon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 22:23:08