created: 2024-03-04T01:43:01.953Z

jest で SyntaxError: Unexpected token '<'

この記事は jest のエラーの話その2。

その1では jest が ESM に対処するための設定をしたが、今回は jest が jsx に対処するための設定をすることになった。

エラーメッセージ

SyntaxError: Unexpected token '<'

テストコード内の < という記号がパースできなくて投げ出している。

tsconfig.json

Next.js で書いているプロジェクトだったので tsconfig.json#jsxpreserve になっている。

"jsx": "preserve",

preserve: Emit .jsx files with the JSX unchanged

preserve は jsx のパースは Next.js 側がやってくれるので、tsc では jsx のパースをしないという設定。 アプリを動かしているときこれで問題ないのだが、ts-jest には jsx をパースする機能がないため、「< は知らない文字なので無理です」というエラーになっている。

tsc に jsx をパースさせてみる

tsc に jsx をパースさせるように設定を変更する。 tsconfig.test.json ファイルを用意してで既存の設定を extends する。

jest.config.js

  ...(中略)
  transform: {
    "^.+\\.(ts|tsx)$": [
      "ts-jest",
      {
        useESM: true,
        tsconfig: "./tsconfig.test.json",
  },

tsconfig.test.json

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "jsx": "react"
  }
}

エラーメッセージ

このままだとまだダメだった。↓ようなエラーになる。

'React' refers to a UMD global, but the current file is a module. Consider adding an import instead.

ググった感じどっちかやらないとダメらしい

  • jsx(tsx) ファイルではimport React する
  • tsconfig.json を "jsx": react-jsx にする

react-jsxreact の違い

jsx 記法は createElement という単なる関数のシンタックスシュガーだが、その関数を使えるようにする import { createElement } from "react" を jsx のパーサーがやるのか、それとも webpack とかのバンドラにやらせるのかの葛藤(というかバンドラごとの実装の違い)が react-jsx というオプションを産んだらしい。

react-jsx についてはこちらがわかりやすかった。

今回は各ファイルで import React することにして、エラーは解消した。

import React, { FC } from "react";
ダークナイト [Blu-ray]
[ad] ダークナイト [Blu-ray]
出演 クリスチャン・ベール, マイケル・ケイン (Blu-ray)