← NestJS コース
30. カスタムデコレータ — パラメータデコレータを自作する
NestJS では createParamDecorator を使って、@Param や @Body のような引数デコレータを自作できます。createParamDecorator に (data, ctx) => ... のファクトリ関数を渡すとデコレータが作られ、ctx.switchToHttp().getRequest() でリクエストを取り出して、必要な値を返すように書きます。代表例は、認証ガードが request.user に入れた値を取り出す @User() です。
実務では、各ハンドラで毎回 @Req() req: Request を受け取って req.user と書く代わりに、@User() user のように意図の明確な1つのデコレータへ集約するために使います。第1引数の data を活かして @User("id") のようにプロパティ名を渡し、特定のフィールドだけ取り出す形にするのも定番です。
つまずきポイントは、デコレータは値を取り出すだけの薄い部品に徹することです。request.user を埋めるのはあくまで既習の認証ガードの仕事で、デコレータ側で認証処理を行うわけではありません。ガードが動いていなければ user は undefined のままなので、両者の役割分担を意識しましょう。
サンプルコード(フレームワーク環境が必要なため表示のみ)
import {
createParamDecorator, ExecutionContext,
Controller, Get, UseGuards,
} from "@nestjs/common";
// 認証ガードが request.user に入れた値を取り出すデコレータ
export const User = createParamDecorator(
(data: string | undefined, ctx: ExecutionContext) => {
const request = ctx.switchToHttp().getRequest();
const user = request.user;
// @User("id") のように渡せば特定のプロパティだけ返す
return data ? user?.[data] : user;
},
);
@Controller("profile")
export class ProfileController {
@Get()
@UseGuards(AuthGuard) // これが request.user を埋める前提
me(@User() user: { id: string; name: string }) {
return user; // req.user をそのまま受け取れる
}
}
サンプルコードで身につける(5本) →
学んだ概念を、素朴な例から実務寄りの例まで5つの具体例で確認します。
公式ドキュメントで詳しく ↗