我正在嘗試為我的應用程式撰寫身份驗證邏輯。我撰寫了一個驗證令牌的中間件,因此我需要req.id. 我必須撰寫一個擴展的介面express.Request才能訪問id(類似的問題)。
import { Request } from "express";
export interface IGetUserAuthInfoRequest extends Request {
id: number;
}
這就是我在中間件中實作介面以便能夠使用該req.id屬性的方式。
export const verifyToken = (req: IGetUserAuthInfoRequest, res: Response, next: NextFunction) => {
req.id = 1; // do something with req.id
/**
* some more logic
**/
next();
}
當我嘗試呼叫中間件時,TypeScript 抱怨,我認為這是因為自定義型別。
app.get("/api/try/admin", verifyToken, (req: Request, res: Response) => {
res.json({message: "try admin"})
});
錯誤看起來像這樣。
Type '(req: IGetUserAuthInfoRequest, res: Response, next: NextFunction)
=> Response | void' is not assignable to type
'ErrorRequestHandler<ParamsDictionary, any, any, ParsedQs, Record<string, any>> |
RequestHandler<ParamsDictionary, any, any, ParsedQs, Record<...>>'.
我怎么能正確輸入(最好不使用any)?
uj5u.com熱心網友回復:
您的自定義中間件與基本 Express 中間件型別(不是其子型別)不兼容。
您的自定義中間件的req 引數比基本中間件的Request引數更專業。在型別理論語言中,您的自定義中間件與基本 Express 中間件的引數型別并不矛盾。函式引數逆變是替換/子型別化的要求。
對此的一種解決方案是關閉strictFunctionChecksintsconfig.json以允許函式引數 bivariance。另一種方法是更改??自定義請求引數的型別以使其與基本型別兼容:
interface IGetUserAuthInfoRequest extends Request {
id?: number // making this optional will make your custom middleware type-compatible
}
通過這些變通方法,您的自定義中間件將被 接受app.get,但其自定義req引數不會傳播到后續中間件和請求/錯誤處理程式。也就是說,req.id仍然是 typeundefined而不是number | undefined在其他地方(它只會在您的自定義中間件中輸入)。
我認為正確的解決方案是使用宣告合并并將您的自定義Request介面合并到Express命名空間。Express公開了此功能供自定義中間件使用:
declare global {
namespace Express {
// These open interfaces may be extended in an application-specific manner via declaration merging.
// See for example method-override.d.ts (https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/method-override/index.d.ts)
interface Request {}
interface Response {}
interface Application {}
}
}
要合并自定義中間件的Request介面:
declare global {
namespace Express {
interface Request {
id?: number
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/354108.html
