gatsby-starter-blogをTypeScriptで書き換えたときのポイント

2020.12.13

💻
TECH

GatsbyJS と TypeScript でブログを作成して公開する(4)

~ gatsby-starter-blog を TypeScript で書き換えたときのポイント ~


前回の投稿は環境構築を紹介しましたが、実際に TypeScript に書き換える段になると、以外につまる部分も出てきます。

今回は、筆者が書き換えをおこなった時に気になったポイントを紹介していきます。

最終的なコードの全体像はこちらのリポジトリをご覧ください。

Prerequisites

前回の記事にしたがって以下の環境構築をおこなった前提で進めていきます。

1. VSCode の利用
2. `gatsby-starter-blog`スターターを使用して Gatsby プロジェクトを作成
3. TypeScript の型チェックのための設定
4. ESLint, Prettier の導入

TypeScript に書き換える手順

手順としては、

  1. .jsの拡張子を.tsxに変更する
  2. 1.でエディターに ESLint のエラーが出るので確認
  3. GraphQL のクエリに名前がついていなければつける
  4. gatsby developコマンドを実行してgatsby-plugin-typegenに型を自動生成させる
  5. 自動生成された型を使用してanyになっている部分を消していく
  6. その他 ESLint のエラーを消していく

といった感じでしょうか。

前回の環境構築でエラーはわかりやすくなっているので、

とにかく tsx にしてエラーを出す方針でいきます。

ポイント

実際に書き換えていった際のポイントをご紹介します。

GraphQL のレスポンスの型の生成

方法そのものは前回の記事で紹介していますので省略します。

ここで気になったのは、生成される型情報についてです。

たとえば、src/pages/index.tsx

export const pageQuery = graphql`
  query BlogIndex {
    site {
      siteMetadata {
        title
        description
      }
    }
  }
`;

とした場合に生成される型情報は以下のようになります。

// src/__generated__/gatsby-types.ts

type BlogIndexQuery = {
  readonly site: Maybe<{
    readonly siteMetadata: Maybe<
      Pick<SiteSiteMetadata, "title" | "description">
    >;
  }>;
};

ここでMaybe<T>が目につきますが、これはgatsby-types.tsの上部にこのように定義されています。

type Maybe<T> = T | undefined;

TypeTundefinedの Union 型になっています。

よって以下のように、


const BlogIndex: React.FC<PageProps<GatsbyTypes.BlogIndexQuery>> = ({
  data,
  location,
}) => {
    // Optional Chainingが必要になる
  const siteTitle = data.site?.siteMetadata?.title || 'Title';

Optional Chaining 演算子?.、Null 合体演算子??、論理和演算子||、Type Guard などが必要になってきます。

変数の末尾に!をつける Non-Null Assertion 演算子もありますが、

ESLint エラーが出るようにしているのでよほどの理由がなければさけるようにします。

gatsby-plugin-typegen の生成がうまくいかないことがある

これはまだ解決策がわかっていないのですが、

gatsby-plugin-typegenで型がうまく生成されないことがあります。

gatsby developコマンドをやり直したり、

クエリ名を削除して保存、付け直して保存を繰り返していると出来たりできなかったり。

また、差分のチェックなどはしていないようで、

gatsby developするたびにsrc/__generated__/gatasby-types.ts が書き変わってしまいます。

しかも、生成される順番も変わっているようで、ソース管理に入れていると、

ちょっと確認する度に変更有になってしまってかなり鬱陶しい。

冪等性のある処理にはならないものなんでしょうか。。。

SEO.tsx の引数の型

編集前のファイルを確認すると下部にこのような記述があります。


SEO.defaultProps = {
  lang: 'en',
  meta: [],
  description: '',
};

SEO.propTypes = {
  description: PropTypes.string,
  lang: PropTypes.string,
  meta: PropTypes.arrayOf(PropTypes.object),
  title: PropTypes.string.isRequired,
}

PropTypes というのはFlowや TypeScript などで型チェックをおこなわない場合にも、

コンポーネントの props の型チェックをするための React のライブラリです。

PropTypes の詳細はこちらの公式のドキュメントを見ていただくとして、

今回は TypeScript をつかうので props の引数の型は自力で作ってあげる必要があります。

このような感じです。


type Props = {
  description?: string;
  lang?: string;
  meta?: HTMLMetaElement[];
  title: string;
};

const SEO: React.FC<Props> = ({ description, lang, meta, title }) => {
/// ...

layout.js を.tsx に変更すると PATH_PREFIX  で怒られる

これに対処するには、定義ファイルを作成する必要があります。

// src/global.d.ts

// eslint-disable-next-line no-underscore-dangle
declare const __PATH_PREFIX__: string;

まとめ

少々短いですが、ここで終わりです。

最終的なプロジェクトの全体はこちらのリポジトリをご覧ください。


Homeへ戻る
profile picture

Kosuke Kihara

I'm a Web Developer👑 who shares tips on Tech, Productivity, Design, and much more!

Kohsuk11KOHSUKkohsuk.tech@gmail.com