Next.js はビルド時にページを生成するための特別な関数を提供しています。App Router になり、getStaticPaths に代わる新しい関数として generateStaticParams が採用されました。この記事では "なぜ generateStaticParams の型を明示したいのか" をまとめます。
ℹ️ 今のところ Page Router でいう GetStaticPaths のような型定義は用意されていません。
型を明示的にするメリット
大きく 2 つのメリットがあると考えています。
- 型駆動開発を取り入れられる。
- 型レベルの整合性を保てるため、誤りの混入するリスクを下げられる。
型駆動開発
プログラミング TypeScript で紹介されていた開発手法です。型を定義してから振る舞いを実装するため、より設計を意識しやすくなります。また、設計である型定義と異なる実装をした場合、TypeScript がエラーで警告してくれます。これによりインターフェースの整合性を保ちつつ、より安全に実装を進めることができます。
型レベルの整合性
"型レベルで整合性が取れている" とはどういう状況でしょうか。例えば、以下のコードを見てください。返り値の型に不整合があるにも関わらず、警告が表示されないため、実行時に 404 エラーを発生させてしまいます。
export const dynamicParams = false;
export async function generateStaticParams() {
return Promise.resolve([
{ product: 'foo' },
{ product: 'bar' },
{ badProduct: 'hoge' }, // プロパティ名の誤り
]);
}
export default function Page({
params: { product },
}: {
params: { product: string };
}) {
return <h1>About {product}</h1>;
}
一方で型を明示的にした場合、上記のような誤りの混入を防ぐことができます。
export const dynamicParams = false;
type Params = {
product: string;
};
type Props = {
params: Params;
};
export async function generateStaticParams(): Promise<Params[]> {
return Promise.resolve([
{ product: 'foo' },
{ product: 'bar' },
{ product: 'hoge' },
]);
}
export default function Page({ params: { product } }: Props) {
return <h1>About {product}</h1>;
}
誤ったプロパティ名として badProduct
を混入させると、TypeScript が警告を上げてくれました。
おわりに
返り値の型を明示的に指定しない限り、generateStaticParams
の params
オブジェクトは any 型となってしまいます。そのため、TypeScript を効果的に活用して、誤りが入りにくいコードを心がけるのが重要だと考えます。
将来的には GenerateStaticParams
のような型が追加されてほしいのですが・・・ 😟