既存のGatsby + ContentfulサイトにTypeScriptを導入したときの手順を書いていきます。
TypeScript設定
以下のコマンドでtsconfig.jsonの追加とtypescriptのインストールを行います。
npm tsc --init
npm install -D typescripttsconfig.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-typegengatsby-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 = createPagesreact-jsxエラー
ここまで実装し、gatsby developコマンドで動作確認するとエラーが発生しました。
React is not definedimport 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