はじめに
とあるnext.jsのアプリについて、もともとbabelでtypescriptをトランスパイルして、Jestでテストするとやっていました。
ただ、Jestの公式にも記載がありますが、
babelを使ったやり方だとコードについて型検査がされずに、結果としてテストコード中のオブジェクトの型が誤っていても、テストが通ってしまうという事象が発生していました。
これをなんとかすべく、ts-jestを使用しようとしたのですが、なかなかうまくいかず、結局、型検査をするnpmスクリプトを書いて解決させました。
その時の備忘録です。
諸事情によりコードが見せられないのですが、「next.js + typescript + jestの組み合わせで、ts-jestを使用しようとしている方」の役に立てれば幸いです。
何故ややこしくなっているのか?
コードをしっかり見たわけではないですが、エラーメッセージを確認する限り、testEnvironmentのデフォルトが node
になっており、このままだと .tsx
のテストがこけて、逆に jsdom
にすると .ts
のテストで instanceof
を使用しているコードを中心にテストがコケるようになってしまいました(型の解釈がbabelを使用した時やと若干異なる模様)。
テストコードによって、testEnvironmentの制御もできないようであり、結局ts-jestの使用は断念せざるを得ませんでした。
どうしたか?
Next.jsの中でbabelが使用されている こともあり、ts-jestよりも開発の効率が少し悪くなったとしても、実行環境との差異を気にしてbabelを使い続けて、 Jestのドキュメントでも書いてあった、tscコマンドで型検査を別途やる という方法を取ることにしました。
具体的にはpacakage.jsonのscriptsに
"type-check": "tsc --pretty --noEmit",
を追加しました。
※ https://github.com/vercel/next.js/blob/canary/examples/with-typescript-eslint-jest/package.json を参考にしました。
また、github actionsでtype-checkコマンドが実行されるようなワークフローを作成し、push時に型検査がされるようにしました。
終わりに
先日出たNext.jsの公式ドキュメント
や、next.jsの公式のexample
も確認してみると、babelを使用しつつ、jestでテストしてました。
ここからは完全に私見ですが、
typescriptを使用しているプロジェクトでjestでテストをするとき、ts-jest
がシンプルで一般的な方法かもしれませんが、Next.js環境下においてはサーバーサイドのコードもフロントエンドのコードも混在するので、技術的に難しいところがあり、おすすめされていないのかもしれません。
また、Next.jsでbabelをもともと使用しているわけだし、環境の差異が発生しないようにbabelを使うのはいい線であるようにも感じました。