ymmr
Recent Articles
    公開日: 2023/10/02

    [Next.js] generateStaticParams の型を厳密にするモチベーション

    Next.js はビルド時にページを生成するための特別な関数を提供しています。App Router になり、getStaticPaths に代わる新しい関数として generateStaticParams が採用されました。この記事では "なぜ generateStaticParams の型を明示したいのか" をまとめます。

    ℹ️ 今のところ Page Router でいう GetStaticPaths のような型定義は用意されていません。

    Are there Typescript types available for new app-dir exports? · vercel/next.js · Discussion #48345Summary I would like to strictly-type (or as strictly-as-possible at least) the exports from new app-dir special files. For example: // app/[language]/layout.tsx /** * ⚠️ pseudo-code, don't copy+pa...github.com

    型を明示的にするメリット

    大きく 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 が警告を上げてくれました。

    おわりに

    返り値の型を明示的に指定しない限り、generateStaticParamsparams オブジェクトは any 型となってしまいます。そのため、TypeScript を効果的に活用して、誤りが入りにくいコードを心がけるのが重要だと考えます。
    将来的には GenerateStaticParams のような型が追加されてほしいのですが・・・ 😟