首页 > 解决方案 > 无法延长快递请求

问题描述

我正在尝试扩展 as 的Request接口Express

import express, { Request, Response } from 'express';
interface IRequest extends Request {
  user: {
    id: string;
  }
}

const router = express.Router();

router.get('/', auth, async (req: IRequest, res: Response) => {
  try {
    const user = await User.findById(req.user.id).select('-password');
    res.json(user);
  } catch (e) {
    console.error((e as Error).message);
    res.status(500).send('Server Error');
  }
});

但我收到以下错误:

没有重载匹配此调用。Overload 1 of 3, '(path: PathParams, ...handlers: RequestHandler<ParamsDictionary, any, any, ParsedQs>[]): Router',给出了以下错误。'(req: IRequest, res: Response) => Promise' 类型的参数不能分配给 'RequestHandler<ParamsDictionary, any, any, ParsedQs>' 类型的参数。参数“req”和“req”的类型不兼容。“Request<ParamsDictionary, any, any, ParsedQs>”类型中缺少属性“user”,但在“IRequest”类型中是必需的。Overload 2 of 3, '(path: PathParams, ...handlers: RequestHandlerParams<ParamsDictionary, any, any, ParsedQs>[]): Router',给出以下错误。'(req: IRequest, res: Response) => Promise' 类型的参数 不可分配给“RequestHandlerParams<ParamsDictionary, any, any, ParsedQs>”类型的参数。类型 '(req: IRequest, res: Response) => Promise' 不可分配给类型 'RequestHandler<ParamsDictionary, any, any, ParsedQs>'.ts(2769)

标签: typescriptexpress

解决方案


打字稿不会让你,因为即使你这样输入:

router.get('/', auth, async (req: IRequest, res: Response) => {

Typescript 仍然会假设 express 将发出 aRequest而不是 a IRequest

但是,由于您可能正在对请求对象进行猴子修补,因此您可以使用声明合并来基本上增加 Express 的内部请求对象:

https://www.typescriptlang.org/docs/handbook/declaration-merging.html

如果您不想全局对 进行此更改Request,您还可以使用断言来确保它确实是IRequest

router.get('/', auth, async (req: request, res: Response) => {
  try {
    assertIRequest(req);
    const user = await User.findById(req.user.id).select('-password');
    res.json(user);
  } catch (e) {
    console.error((e as Error).message);
    res.status(500).send('Server Error');
  }
});

function assertIRequest(req: Request|IRequest): asserts req is IRequest {
  if (!req?.user?.id) throw new Error('Request was not an IRequest');
}

推荐阅读