既存のGatsby + ContentfulサイトにTypeScriptを導入したときの手順を書いていきます。
TypeScript設定
以下のコマンドでtsconfig.json
の追加とtypescript
のインストールを行います。
npm tsc --init
npm install -D typescript
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
モジュールをどのように解決するのかを指定します。指定する値はnode
かclassic
です。
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
内に記述していきます。
export const createPages: GatsbyNode['createPages'] = async ({
graphql,
actions: { createPage }
}) => {
...
})
そして、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の設定を行うことで上記のエラーを解決することができるようです。 各設定ファイルに以下を追記します。
export const onCreateBabelConfig: GatsbyNode['onCreateBabelConfig'] = ({ actions: {setBabelPlugin} }) => {
setBabelPlugin({
name: '@babel/plugin-transform-react-jsx',
options: {
runtime: 'automatic',
},
});
};
@babel/plugin-transform-react-jsxドキュメント
require('ts-node').register({
compilerOptions: {
module: 'commonjs',
target: 'es2019',
},
})
const {
createPages,
onCreateBabelConfig,
} = require("./gatsby-node/index")
exports.createPages = createPages
exports.onCreateBabelConfig = onCreateBabelConfig