Express路由调用返回中间件的函数时TypeScript类型报错求解决
自定义Express中间件
validateBody的TypeScript类型兼容问题解决 问题场景
我正在实现一个用于API请求体验证的自定义函数validateBody,代码如下:
export function validateBody(schema: string): (req: ExpressRequest, res: ExpressResponse, next: ExpressNextFunction) => void { return function (req: ExpressRequest, res: ExpressResponse, next: ExpressNextFunction): void | ExpressResponse { // 验证逻辑 next(); } }
在Express路由中以返回中间件的方式调用:
router.route('/api/users/currentuser').get(validateBody('signIn'), (req: ExpressRequest, res: ExpressResponse, next: ExpressNextFunction) => { // 路由处理逻辑 });
此时出现TypeScript lint错误:
No overload matches this call. The last overload gave the following error. Argument of type '(req: ExpressRequest, res: ExpressResponse, next: ExpressNextFunction) => void' is not assignable to parameter of type 'RequestHandlerParams<ParamsDictionary, any, any, ParsedQs, Record<string, any>>'. Type '(req: ExpressRequest, res: ExpressResponse, next: ExpressNextFunction) => void' is not assignable to type 'RequestHandler<ParamsDictionary, any, any, ParsedQs, Record<string, any>>'. Types of parameters 'req' and 'req' are incompatible. Property 'value' is missing in type 'Request<ParamsDictionary, any, any, ParsedQs, Record<string, any>>' but required in type 'ExpressRequest'.ts(2769) types.ts(4, 5): 'value' is declared here. index.d.ts(222, 5): The last overload is declared here.
直接使用RequestHandlerParams类型约束validateBody返回值时,函数定义又会报错。使用JavaScript开发时无此问题,需要可行的解决方案或变通方法。
解决方案
1. 修正自定义请求类型的继承关系
你的ExpressRequest是自定义类型,必须确保它继承自Express官方的Request类型,才能与路由中间件的类型系统兼容:
// types.ts import { Request } from 'express'; export interface ExpressRequest extends Request { value?: any; // 根据实际业务定义属性的具体类型 }
2. 用Express原生RequestHandler约束返回值
直接使用Express提供的RequestHandler类型来定义validateBody的返回值,避免手动声明参数类型,让类型系统自动匹配:
import { RequestHandler, Response, NextFunction } from 'express'; import { ExpressRequest } from './types'; export function validateBody(schema: string): RequestHandler { return function (req: ExpressRequest, res: Response, next: NextFunction): void | Response { // 验证逻辑 next(); } }
由于ExpressRequest继承了原生Request,这里的参数类型会被自动识别为合法的中间件参数类型。
3. 临时类型断言(变通方案)
如果暂时无法修改类型定义,可以在路由调用时使用类型断言跳过检查:
import { RequestHandler } from 'express'; router.route('/api/users/currentuser').get( validateBody('signIn') as RequestHandler, (req: ExpressRequest, res: Response, next: NextFunction) => { // 路由处理逻辑 } );
注意:此方法会绕过TypeScript的类型校验,仅作为临时应急方案,不推荐长期使用。
内容的提问来源于stack exchange,提问作者DrusePstrago
相关产品推荐
相关产品推荐

