← 解説「カスタムパイプ — transform の契約」に戻る
サンプルコードで身につける: カスタムパイプ — transform の契約
解説で学んだ概念を、5つの具体例で確認します。素朴な例から実務寄りの例へと進みます。
1組み込みの ParseIntPipe を使う
前のレッスンで保留にした「@Param は文字列」問題を解決する組み込みパイプの例です。引数単位でパイプを差し込むと、ハンドラに届く時点で値が変換済みになります。変換できなければ自動で 400 が返ります。
import { Controller, Get, Param, ParseIntPipe } from "@nestjs/common";
@Controller("users")
export class UsersController {
// /users/42 → id は number の 42 になる
// /users/abc → パイプが弾いて自動で 400 Bad Request
@Get(":id")
findOne(@Param("id", ParseIntPipe) id: number) {
return { id, idType: typeof id }; // "number"
}
}
// 「@Param は文字列」問題は ParseIntPipe で解決するのが定番
2自作の TrimPipe
前後の空白を取り除いてからハンドラへ渡す自作パイプです。PipeTransform の transform() を実装するだけで組み込みパイプと同列に使える、という「契約を満たせば何でもパイプ」の感覚を掴む例です。
import { Injectable, PipeTransform } from "@nestjs/common";
@Injectable()
export class TrimPipe implements PipeTransform<string, string> {
transform(value: string): string {
// 前後の空白を取り除いてからハンドラへ渡す
return value.trim();
}
}
// 適用例: 検索キーワードの正規化
// @Get("search")
// search(@Query("keyword", TrimPipe) keyword: string) { ... }
//
// 「値を受け取り、変換して返す」契約を満たせば何でもパイプになる
3既定値を補うパイプを再現
値が未指定のときに既定値を補う、というパイプの発想をプレーン TypeScript で再現した例です。NestJS 組み込みの DefaultValuePipe と同じ仕組みで、「変換」には値の補完も含まれることが分かります。
TypeScript
4値を2択に制限するパイプ
並び順の指定を asc / desc の2択に制限する自作パイプです。変換だけでなく「不正なら例外を投げて弾く」のもパイプの契約の一部であり、ハンドラには検証済みの値しか届かない状態を作れます。
import { Injectable, PipeTransform } from "@nestjs/common";
// 並び順の指定を "asc" / "desc" の2択に制限するパイプ
@Injectable()
export class ParseSortOrderPipe implements PipeTransform<string, string> {
transform(value: string): string {
if (value !== "asc" && value !== "desc") {
// 実際の NestJS では 400 になる専用の例外を投げる
throw new Error("sort は asc か desc を指定してください");
}
return value;
}
}
// 適用例: @Query("sort", ParseSortOrderPipe) sort: string
// ハンドラに届く時点で「2択のどちらか」であることが保証される
5CSVクエリを配列に変換する
?tags=nestjs,typescript のようなカンマ区切りクエリを配列へ変換する実務パイプです。空白の除去や未指定時の空配列化までパイプ内で済ませることで、ハンドラには正規化済みの配列だけが届きます。
import { Injectable, PipeTransform } from "@nestjs/common";
// GET /articles?tags=nestjs, typescript ,api のような
// カンマ区切り文字列を正規化済みの string[] に変換する
@Injectable()
export class ParseCsvPipe
implements PipeTransform<string | undefined, string[]>
{
transform(value: string | undefined): string[] {
if (value === undefined || value === "") return [];
return value
.split(",")
.map((item) => item.trim())
.filter((item) => item !== "");
}
}
// 使う側: @Query("tags", ParseCsvPipe) tags: string[]
// 絞り込み検索 API のタグ・ID リスト受け取りで頻出のパターン