logo
Gatsby+ContentfulサイトにTypeScriptを導入する
2022年02月16日

Gatsby+ContentfulサイトにTypeScriptを導入する

既存のGatsby + ContentfulサイトにTypeScriptを導入したときの手順を書いていきます。

TypeScript設定

以下のコマンドでtsconfig.jsonの追加とtypescriptのインストールを行います。

npm tsc --init
npm install -D typescript

tsconfig.jsonは以下のように設定します。

tsconfig.json
{
  "include": ["./src/**/*"],
  "compilerOptions": {
    "target": "es2019",
    "module": "es2020",
    "jsx": "react-jsx",
    "strict": true,
    "moduleResolution": "node",
    "importsNotUsedAsValues": "error",
    "forceConsistentCasingInFileNames": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true,
    "noUncheckedIndexedAccess": true,
  }
}

tsconfig.jsonオプションについて

それぞれのオプションについて書いていきます。

include

コンパイル対象のファイルを指定します。ワイルドカード(*)を使用することができます。

target

どのバージョンのjsを出力するかを書きます。

module

出力するjsのモジュールの仕組みとして何を使用するかを指定します。

jsx

jsx変換タイプを選択します。 以下の記事がとても参考になりました。 React17におけるJSXの新しい変換を理解する

strict

strictをtrueにすると、以下の各オプションが全てtrueになります。

  • alwaysStrict
  • strictNullChecks
  • strictBindCallApply
  • strictFunctionTypes
  • strictPropertyInitialization
  • noImplicitAny
  • noImplicitThis
  • useUnknownInCatchVariables

moduleResolution

モジュールをどのように解決するのかを指定します。指定する値はnodeclassicです。

importsNotUsedAsValues

interfaceなど型の定義だけを持つのファイルのインポートは、import typeでインポートしないと、コンパイルエラーにします。

forceConsistentCasingInFileNames

ファイルの文字列の大文字小文字を区別するかどうかを指定します。OSによっては、大文字小文字を区別出来ない場合があるため、trueにしておくと良いです。

noImplicitReturns

関数の戻り値がvoid以外のときにreturnを必須にします。

noFallthroughCasesInSwitch

switch文で、caseをbreakやreturnで終えていることを必須にします。

noUncheckedIndexedAccess

インデックス型や配列で宣言されたオブジェクトが持つプロパティへのアクセスを厳密に評価します。

GraphQLレスポンスの型生成

GraphQLのレスポンスの型をgatsby-plugin-typegenを使って生成します。

npm install gatsby-plugin-typegen

gatsby-config.jsのpluginにgatsby-plugin-typegenを追記します。 その後、gatsby buildを実行すると、src/__generated__/gatsby-types.tsにGraphQLリクエストの方定義が生成されます。

コンポーネントファイルのTypeScript化

各コンポーネントファイルの拡張子を.jsから.tsxに書き換え、各データに型をつけていきます。 先ほど生成したGraphQLの型を使用する場合は以下のように書きます。

type Props = {
  data: GatsbyTypes.ArticlesQuery
}

gatsby-node.jsのTypeScript化

nodeでTypeScriptを動かすために、ts-nodeをインストールします。

npm install -D ts-node

そしてGatsby Node APIs関連処理をgatsby-node/index.ts内に記述していきます。

gatsby-node/index.ts
export const createPages: GatsbyNode['createPages'] = async ({
  graphql,
  actions: { createPage }
}) => {
  ...
})

そして、gatsby-node.jsで上記の内容を読み込みます。

gatsby-node.js
require('ts-node').register({
  compilerOptions: {
    module: 'commonjs',
    target: 'es2019',
  },
})

const {
  createPages,
} = require("./gatsby-node/index")

exports.createPages = createPages

react-jsxエラー

ここまで実装し、gatsby developコマンドで動作確認するとエラーが発生しました。

React is not defined

import react from 'React'を追記すればエラーは出なくなるのですが、react-jsxの設定ではこの記述は不要なはずです。

んー...と色々調べてみたところ以下のやりとりを見つけました。

React 17 new JSX Transform: ReferenceError: React is not defined

どうやらGatsby内のBabelではデフォルトでreact-jsxへの変換を無効にしているようです。 GatsbyとBabelについての詳細は追々調査してみます...

Gatsby Node APIsのonCreateBabelConfigの設定を行うことで上記のエラーを解決することができるようです。 各設定ファイルに以下を追記します。

gatsby-node/index.ts
export const onCreateBabelConfig: GatsbyNode['onCreateBabelConfig'] = ({ actions: {setBabelPlugin} }) => {
  setBabelPlugin({
    name: '@babel/plugin-transform-react-jsx',
    options: {
      runtime: 'automatic',
    },
  });
};

@babel/plugin-transform-react-jsxドキュメント

gatsby-node.js
require('ts-node').register({
  compilerOptions: {
    module: 'commonjs',
    target: 'es2019',
  },
})

const {
  createPages,
  onCreateBabelConfig,
} = require("./gatsby-node/index")

exports.createPages = createPages
exports.onCreateBabelConfig = onCreateBabelConfig

参考

©︎ 2022 uuuno