我正在编写一个基于Jason Watmore的用户认证样板的用户认证中间件。
我期望的结果是这段代码“正常工作”,因为它是从另一个项目复制来的,在那里它确实是这样做的。
我的实际结果是得到了这条很长的错误消息:
(alias) authorize(roles?: Role[]): ({
(req: express.Request<ParamsDictionary, any, any, QueryString.ParsedQs, Record<string, any>>, res: express.Response<...>, next: express.NextFunction): Promise<...>;
unless: (options: Params) => {
...;
};
} | ((request: RequestWithUser, res: express.Response<...>, next: express.NextFunction) => Promise<...>))[]
import authorize
No overload matches this call.
The last overload gave the following error.
Argument of type '({ (req: Request<ParamsDictionary, any, any, ParsedQs, Record<string, any>>, res: Response<any, Record<string, any>>, next: NextFunction): Promise<...>; unless: (options: Params) => { ...; }; } | ((request: RequestWithUser, res: Response<...>, next: NextFunction) => Promise<...>))[]' is not assignable to parameter of type 'RequestHandlerParams<ParamsDictionary, any, any, ParsedQs, Record<string, any>>'.
Type '({ (req: Request<ParamsDictionary, any, any, ParsedQs, Record<string, any>>, res: Response<any, Record<string, any>>, next: NextFunction): Promise<...>; unless: (options: Params) => { ...; }; } | ((request: RequestWithUser, res: Response<...>, next: NextFunction) => Promise<...>))[]' is not assignable to type '(ErrorRequestHandler<ParamsDictionary, any, any, ParsedQs, Record<string, any>> | RequestHandler<ParamsDictionary, any, any, ParsedQs, Record<...>>)[]'.
Type '{ (req: Request<ParamsDictionary, any, any, ParsedQs, Record<string, any>>, res: Response<any, Record<string, any>>, next: NextFunction): Promise<...>; unless: (options: Params) => { ...; }; } | ((request: RequestWithUser, res: Response<...>, next: NextFunction) => Promise<...>)' is not assignable to type 'ErrorRequestHandler<ParamsDictionary, any, any, ParsedQs, Record<string, any>> | RequestHandler<ParamsDictionary, any, any, ParsedQs, Record<...>>'.
Type '(request: RequestWithUser, res: Response, next: NextFunction) => Promise<Response<any, Record<string, any>> | undefined>' is not assignable to type 'ErrorRequestHandler<ParamsDictionary, any, any, ParsedQs, Record<string, any>> | RequestHandler<ParamsDictionary, any, any, ParsedQs, Record<...>>'.
Type '(request: RequestWithUser, res: Response, next: NextFunction) => Promise<Response<any, Record<string, any>> | undefined>' is not assignable to type 'ErrorRequestHandler<ParamsDictionary, any, any, ParsedQs, Record<string, any>>'.
Types of parameters 'res' and 'req' are incompatible.
Type 'Request<ParamsDictionary, any, any, ParsedQs, Record<string, any>>' is missing the following properties from type 'Response<any, Record<string, any>>': status, sendStatus, links, send, and 53 more.ts(2769)
index.d.ts(163, 5): The last overload is declared here.
No quick fixes available
下面是违规代码
function authorize(roles: Role[] = []) {
if (typeof roles === "string") {
roles = [roles];
}
return [
jwt({
secret, // authenticate JWT token and attach user to request object (req.user)
algorithms: ["HS256"],
}),
// problem is caused here with "RequestWithUser"
async (request: RequestWithUser, res: Response, next: NextFunction) => {
const acctInfo = request.auth;
if (acctInfo?.acctId === undefined) {
return res.status(401).json({ message: "Unauthorized" });
}
request.user = {
acctId: acctInfo.acctId,
role: "", // temp to satisfy ts
};
const account: Account | null = await acctDAO.getAccountById(acctInfo.acctId);
if (!account) return res.status(401).json({ message: "Unauthorized" });
const refreshTokens = await rtDAO.getAllRefreshTokensForAccount(account.acctId);
const validRoles = Object.values(Role);
const acctRole: Role = account.role as Role;
const rolesFoundOnRequest = roles.length;
if (rolesFoundOnRequest && !validRoles.includes(acctRole)) {
return res.status(401).json({ message: "Unauthorized" });
}
request.user.role = account.role;
request.user.ownsToken = (token: string) => !!refreshTokens.find((x: any) => x.token === token);
next();
},
];
}
export default authorize;
当我将RequestWithUser
改回Request
时,错误消失了,但这不起作用,因为中间件的其余部分将出现预期错误类型的TS错误。
如您所见,RequestWithUser
只是一个扩展的Express Request
:
export interface RequestWithUser extends Request {
user?: {
role: string;
ownsToken?: Function;
acctId: number;
};
auth?: {
sub: any;
acctId: number;
};
}
我完全不明白这个错误信息,它似乎是在说“express将把这个传递给ErrorRequestHandler
,形状不合适”,但我完全不清楚发生了什么。
编辑:所以很明显我应该告诉你错误出现在哪里。2下面的路由都是错误出现在哪里的例子。
this.router.get("/", authorize([Role.Admin]), this.getAllAccounts);
this.router.get("/:id", authorize(), this.getAccountById);
this.router.post("/", authorize([Role.Admin]), createAccountSchema, this.createAccount);
this.router.put("/:id", authorize(), updateRoleSchema, this.updateAccount);
1条答案
按热度按时间46qrfjad1#
RequestWithUser
只是扩展的ExpressRequest
不要创建一个特定的接口(即使它扩展了
Request
),而是使用声明合并来 * 扩充 * 实际的Request
接口本身。问题不在于运行时代码,而在于额外的类型。
错误消息本身确实具有误导性,但它是由不同的第一个参数类型直接导致的。
因为它不匹配通常的
Request
类型,TypeScript尝试推断一个不同的函数重载,并以一个应该接受普通RequestHandler和ErrorRequestHandler的混合的重载结束...但是您的函数不能同时处理这两个类型,因此出现了错误消息。