export const CurrentUser = createParamDecorator(
(data: string | undefined, ctx: ExecutionContext) => {
const user = ctx.switchToHttp().getRequest().user;
return data ? user?.[data] : user;
},
);
@Get("me")
me(@CurrentUser() user: UserPayload, @CurrentUser("id") id: string) {}
Create it with createParamDecorator(). It reads the user in one place, so handlers don't each need the raw request.
How it works. createParamDecorator() takes a factory function. The factory receives two things:
data: the argument passed to the decorator, for example a property name- the
ExecutionContext
Whatever the factory returns becomes the handler's parameter. Here it reads req.user, which the auth guard set earlier. It can return a single property if data names one.
Why it is better than @Req() in every handler:
- Handlers declare exactly what they need.
- Handlers don't depend on platform types like the Express request.
- Handlers are easier to unit test: you just pass a user object.
- The logic lives in one place. You can extend it for other contexts, for example reading the user from
GqlExecutionContextin GraphQL resolvers.
Custom param decorators also work with pipes. For example: @CurrentUser(new ValidationPipe({ validateCustomDecorators: true })).
- Create it with
createParamDecorator((data, ctx) => ...). - It reads
req.user, which the auth guard set. - The
dataargument can select one property of the user. - Handlers avoid
@Req(), so they are easier to test. - There is one place to adapt it for GraphQL or WebSockets.
Read more