我正在尝试将
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');
}
});
但我收到以下错误:
没有重载与此调用匹配。 重载第 1 个(共 3 个)“(path: PathParams, ...handlers: RequestHandler
[]): Router”,出现以下错误。 类型“(req: IRequest, res: Response) => Promise”的参数不可分配给“RequestHandler ”类型的参数。 参数“req”和“req”的类型不兼容。 “Request ”类型中缺少属性“user”,但“IRequest”类型中需要属性“user”。 重载第 2 个(共 3 个)“(path: PathParams, ...handlers: RequestHandlerParams []): Router”,出现以下错误。 类型“(req: IRequest, res: Response) => Promise”的参数不可分配给“RequestHandlerParams ”类型的参数。 类型“(req: IRequest, res: Response) => Promise”不可分配给类型“RequestHandler ”.ts(2769)
Typescript 不会让你这么做,因为即使你这样输入:
router.get('/', auth, async (req: IRequest, res: Response) => {
Typescript 仍然会假设 Express 会发出
Request
而不是 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');
}
假设接口
IRequest
除上述用途外没有用于其他目的,可以按照Antonello Zanini的这篇博客文章中的路线:只需通过添加声明文件来扩展express定义的接口 src/types/express/index.d.ts
包含以下内容:
// src/types/express/index.d.ts
// to make the file a module and avoid the TypeScript error
export {}
declare global {
namespace Express {
export interface Request {
user: {
id: string;
}
}
}
}
与另一个答案一样,TypeScript 的 声明合并 机制会将两个声明融合为一个。
希望这个迟来的答案对一些读者有用。我刚刚有一个类似的问题。