我可以在打字稿中轻松扩展 express.Request,例如:
interface MyRequest extends express.Request {
userId: string;
}
但是,如果我编写一个使用它的中间件函数,例如:
const myMiddlewareFn = (req: MyRequest, res: express.Response) => {
req.userId; // <-- this works as a string
}
app.get('/user', myMiddlewareFn) // <-- this does NOT type-check because MyRequest is more narrow than express.Request.
我看到很多关于如何扩展 express.Request 的讨论。我怎样才能在我的路线中正确地进行类型检查?
目前我正在做这样的事情:
/**
* @param allowedRoles see HasuraCustomClaims
* @param handlerFn the final business logic
* @returns an array of middleware, correctly typed for the handlerFn
*/
export function addApiAuthMiddleware(
allowedRoles: string[],
...handlerFns: (
| ((req: OTApiAuthorizedRequest, res: Response) => Promise<void>)
| ((req: OTApiValidatedAndAuthorizedRequest<any>, res: Response) => Promise<void>)
)[]
): express.RequestHandler[] {
return [
decodeIdToken,
guardRequestHandler(createRoleAuthMiddleware(allowedRoles)),
...handlerFns.map((handlerFn) => guardRequestHandler(handlerFn)),
];
}
/**
* This typecasting is a *little* jank.
*
* @param middlewareOrHandlerFn either api middleware or a final api handler function
* @returns
*/
export function guardRequestHandler<T extends Request>(
middlewareOrHandlerFn:
| ((req: T, res: Response, next: express.NextFunction) => Promise<void>)
| ((req: T, res: Response) => Promise<void>),
): express.RequestHandler {
return (middlewareOrHandlerFn as unknown) as express.RequestHandler;
}
// this below type-checks
app.get('/user', ...addApiAuthMiddleware(['admin'], userHandlerFn));
有更好的方法吗?
答案 0 :(得分:0)
您可以将 app.get('/user', myMiddlewareFn) 更改为 app.get('/user', myMiddlewareFn as any) 或 app .get('/user', myMiddlewareFn) 这些是相同的,并且都是编译时转换。 不是运行时。
答案 1 :(得分:0)
设置您的自定义属性是可选属性。
interface MyRequest extends express.Request {
userId?: string; // userId is optional
}
在您的中间件或请求处理程序中,您始终需要确保 userId
不是未定义的。
const myMiddlewareFn = (req: MyRequest, res: express.Response) => { // missing next function ?
if (req.userId) {
// do something with userId
req.userId; // <-- this works as a string
}
}