mongolyyのブログ

開発(Javascript, Typescript, React, Next.js)や開発手法(スクラム, アジャイル)、勉強したことについて色々書ければと。

next.js + typescript + jestの組み合わせで、ts-jestでうまくいかないときはbabel+型検査をすれば良いんじゃないかと思った話

はじめに

とあるnext.jsのアプリについて、もともとbabelでtypescriptをトランスパイルして、Jestでテストするとやっていました。

ただ、Jestの公式にも記載がありますが、

jestjs.io

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の公式ドキュメント

nextjs.org

や、next.jsの公式のexample

github.com

も確認してみると、babelを使用しつつ、jestでテストしてました。

ここからは完全に私見ですが、
typescriptを使用しているプロジェクトでjestでテストをするとき、ts-jest がシンプルで一般的な方法かもしれませんが、Next.js環境下においてはサーバーサイドのコードもフロントエンドのコードも混在するので、技術的に難しいところがあり、おすすめされていないのかもしれません。 また、Next.jsでbabelをもともと使用しているわけだし、環境の差異が発生しないようにbabelを使うのはいい線であるようにも感じました。