メインコンテンツへスキップ

Gatsby で GraphQL 実行結果の型を作成する

·2 分
Gatsby GraphQL

Gatsby は基本的に TypeScript 対応を謳っているため、

  • コンポーネントファイルを .tsx の認識
  • ページコンポーネント用の型定義
  • gatsby-config.jsgatsby-node.js の型定義
  • @types/react , @types/react-dom の利用

は何もせずとも出来ます。
しかしながら、 GraphQL の実行結果が any になってしまうため、型対応のためにはプラグインを入れて対応します。

前提と準備
#

  • Gatsby は導入済みとします。
1$ gatsby --version
2Gatsby CLI version: 3.3.0
  • シンプルなスターターからプロジェクトを作成しておきます。
1$ gatsby new example-website https://github.com/gatsbyjs/gatsby-starter-hello-world
  • パッケージマネージャーは yarn を利用します。
  • プロジェクトのディレクトリ配下に入り、以下のコマンドで gatsby-plugin-typegen のプラグインをインストールします。
    • 同様のプラグインとして gatsby-plugin-graphql-codegen がありますが、2021年5月時点では、-typegen のほうが推奨のようです。
1$ yarn add gatsby-plugin-typegen
  • 設定ファイル gatsby-config.js にプラグインを追記します。また、 GraphQL で扱うデータ(自サイトに関するメタデータ)も追記しておきます。
 1module.exports = {
 2  siteMetadata: {
 3      title: `OKAZAKI Shogo's Website`,
 4      author: {
 5        name: `OKAZAKI Shogo`,
 6        summary: `OKAZAKI Shogo's Website.`,
 7      },
 8      siteUrl: `https://www.zakioka.net/`,
 9      social: {
10        twitter: `tsuchinoko0402`,
11        github: `tsuchinoko0402`,
12      },
13    },
14    plugins: [
15      `gatsby-plugin-typegen`
16    ],
17  }
  • ここで記述したサイトのメタデータは、ビルド完了後、以下の GraphQL のクエリで取得できます:
 1query MyQuery {
 2  site {
 3    siteMetadata {
 4      siteUrl
 5      title
 6      author {
 7        name
 8        summary
 9      }
10      social {
11        github
12        twitter
13      }
14    }
15  }
16}

ビルドして型情報を見る
#

  • stc/index.jssrc/index.tsx に変更し、以下の内容で作成します。
 1import React from "react"
 2import { graphql, PageProps } from "gatsby"
 3
 4const IndexPage: React.FC<PageProps> = () => {
 5  return(
 6    <>
 7      <div>Hello, World!</div>
 8    </>
 9  )
10}
11
12export const query = graphql`
13  query IndexPage {
14    site {
15      siteMetadata {
16        siteUrl
17        title
18        author {
19          name
20          summary
21        }
22        social {
23          github
24          twitter
25        }
26      }
27    }
28  }
29`
30
31export default IndexPage
  • yarn build でビルドすると、 src/__generated__/gatsby-types.ts が生成されます。
    • このファイル内に以下のような IndexPageQuery の型情報が作成されます。
    • プラグインにより、ページコンポーネント内に query XXXを作成したら、XXXQuery という名前の型が自動的に作成されます。
1type IndexPageQuery = { readonly site: Maybe<{ readonly siteMetadata: Maybe<(
2      Pick<SiteSiteMetadata, 'siteUrl' | 'title'>
3      & { readonly author: Maybe<Pick<SiteSiteMetadataAuthor, 'name' | 'summary'>>, readonly social: Maybe<Pick<SiteSiteMetadataSocial, 'github' | 'twitter'>> }
4    )> }> };
5}
  • これをページコンポーネントで利用します。下記のように index.tsx を変更します:
    • React.FC<PageProps<GatsbyTypes.[生成した型]>> という指定の仕方をします。
 1import React from "react"
 2import { graphql, PageProps } from "gatsby"
 3
 4const IndexPage: React.FC<PageProps<GatsbyTypes.IndexPageQuery>> = ({ data }) => {
 5  return(
 6    <>
 7      <pre>
 8        {JSON.stringify(data, null, 2)}
 9      </pre>
10    </>
11  )
12}
13
14export const query = graphql`
15  query IndexPage {
16    site {
17      siteMetadata {
18        siteUrl
19        title
20        author {
21          name
22          summary
23        }
24        social {
25          github
26          twitter
27        }
28      }
29    }
30  }
31`
32
33export default IndexPage
  • 再ビルドが完了すると、以下のように表示されます。

まとめ
#

  • Gatsby が TypeScript に対応しきれていない GraphQL の実行結果の型情報を自動生成するプラグインを利用しました。
  • これでだいたい Gatsby で問題なく TypeScript を利用できています。
    • gatsby-config.jsgatsby-node.js も TypeScript 対応するためには一工夫しなければならないのですが、特に大きな問題もないので一旦そのままにしています。