TypeScript導入時はコンポーネント内に自分でPropsの型を書いていましたが、全てのコンポーネントでこれを行うと非常に面倒かつ、GraphQLのスキーマとオリジナルの型で二重に型を生成することになるので、自動生成するプラグインを導入してコンポーネントから利用します。
gatsby-plugin-graphql-codegen
の導入
npmでインストールした後、生成するtypesファイルの宛先と監視するディレクトリを指定します。 これらはGraphQLのクエリを生成する部分が指定してあればよいので、特に目立った構成変更をしていない自分の場合はREADMEの指定をそのまま利用しました。
{ resolve: "gatsby-plugin-graphql-codegen", options: { fileName: "types/graphql-types.ts", documentPaths: [ "./src/**/*.{ts,tsx}", "./node_modules/gatsby-*/**/*.js" ], codegenDelay: 200 } },
出力先fileName
は監視するディレクトリdocumentPaths
と同じ場所にしてしまうと自分を参照して無限ループになるので注意。
これで、ローカルサーバーを起動した後にクエリに変更を行うとプロジェクト内で使える型データがtypes/graphql-types.ts
に吐き出されます。
コンポーネント内で型を利用する
前回までは自分で型を書いていました。
interface StaticQueryProps { allMarkdownRemark: { edges: Edge[] } } interface Edge { node: { frontmatter: { date: string title: string } id: string } } const recentPost: React.FC = () => ( <StaticQuery query={graphql` query RecentPostQuery { allMarkdownRemark(limit: 4, sort: { fields: frontmatter___date, order: DESC }) { edges { node { frontmatter { date(formatString: "YYYY/MM/DD") title } id } } } } `} // render
自動生成した型を使うために、import文を1行書いて型情報を読み込みます。
この場合、GraphQLのクエリに名称をつけておくと[Query名]Query
という名称で型情報が出力されます。
~Queryという名前をクエリにつけていたので、~QueryQueryという型にならないよう全て書き直しました…
//...import import { RecentPostQuery } from "../../types/graphql-types" const sportsPost: React.FC = () => { const data: RecentPostQuery = useStaticQuery( graphql` query RecentPost { allMarkdownRemark( sort: { fields: frontmatter___date, order: DESC } limit: 4 ) { edges { node { frontmatter { date(formatString: "YYYY/MM/DD") title cover { childImageSharp { fluid { src } } } } id fields { slug } } } } } ` ) //render
VScodeの補完と参照もバッチリ効くので、もうPropsの中身を見る度にあっちこっちのコンポーネントを見る必要なし!
欠点
各Functionの返り値を明確に意識する必要が出てきます。本来なら当たり前ですが、Vanilla JSだとよしなに書いても問題なく動いてしまうので、最初は苦労しました…