はじめに
Next.jsで動的ルートを使う際、URLパラメータはstring | undefined
型として受け取りますが、実際のアプリケーションでは特定の値のみを許可したいケースが多く存在します。
しかし、型安全性が担保されていないと不正な値でも実行時エラーにならないため、バグの原因となってしまいます。
そのため、動的ルートパラメータの型安全性を確保する仕組みが必要になります。
問題
ECサイトで商品カテゴリページを作る場面を想定して下さい。
/products/electronics
、/products/books
、/products/clothing
のようなURLで、カテゴリ別に商品を表示したいので、Next.jsの動的ルートを使って実装します。
// pages/products/[category].tsx
export default function ProductsPage() {
const params = useParams<{ category: string }>()
// params.category に応じて商品を表示
return <ProductList category={params.category} />
}
ここで、Next.jsの動的ルート[category]
で受け取ったパラメータはstring | undefined
型ですが、実際は特定の値('electronics'
、'books'
、'clothing'
)のみが有効なので、型安全ではなくなってしまいます。
// ❌ 不正なURLでもエラーにならない
// /products/toys にアクセスした場合
const category = params.category // "toys"
setCurrentCategory(category) // 意図しない値がセットされる
// ❌ 実行時エラーの原因になりうる
const apiUrl = `/api/products/${category}` // 存在しないAPIエンドポイント
解決策
as const
と型ガードを使って型安全にチェック
export const CategoryValues = {
Electronics: 'electronics',
Books: 'books',
Clothing: 'clothing',
} as const
export type Category = (typeof CategoryValues)[keyof typeof CategoryValues]
export const isCategory = (param: string | undefined): param is Category => {
return param
? Object.values(CategoryValues).some((value) => value === param)
: false
}
使用例
const params = useParams<{ category: string }>()
const category = isCategory(params.category) ? params.category : 'electronics'
setCurrentCategory(category)
まとめ
数行のコードを追加することで、型安全性を確保できるようになりました。
この実装パターンは他の動的ルート(ユーザーロール、ステータスなど)にも応用できるので必要に応じて実装をしてみて下さい。