VSCodeでJest

最近はどうしてもコード書く機会が少ないので、JetBrains製品のサブスクリプションを維持するのを諦めてこれまで食わず嫌いだったVSCodeに移行したのですが、改めてコード書き始めるとちょいちょいハマったのでメモっておかねば。for 未来の私。

課題

TypeScript + Jestが今までの作法で動かなかった。

解決

必要パッケージを追加する。本体に必要なパッケージ群は別に、Jestで必要なものたちは...

$ yarn add typescript jest ts-jest @types/jest

http://mk.hatenablog.com/archive/2019/05/17

おなじみts-jestはpreset一発で細々としたjest設定が終わり超楽。ドキュメントによるとプリセットは混在する.jsの処理の違いで複数用意されている。テストコードがTypeScriptオンリーなら値は"ts-jest"。そういえばこれ、前にやりました

// package.jsonの関係あるとこだけ抜粋
{
    "jest": {
        "preset": "ts-jest"
    },
    "devDependencies": {
        "@types/jest": "^24.0.19",
        "jest": "^24.9.0",
        "ts-jest": "^24.1.0",
        "typescript": "^3.6.3"
    }
}

ここで問題発生。VSCodeのIntellisenseが期待通りに動作せず、グローバルスコープの、describe・it・jestの名前解決ができない。WEBを調べるとプロジェクトルートにjsconfig.jsonを書けとか見つけたので、VSCodeのドキュメントの該当ページにあたって設定してみたりするも改善しない。

その後にtsconfig.jsonを試行錯誤する中で、以下が当たりだった。 "typeRoots": [ "./node_modules/@types" ] で型ファイルを明示的に取り込んでる。非グローバルはimportでコード上に明示されるのでそもそもに解決できるけど、暗黙となってしまうグローバルの型はここで探索する。これまで経験してきたJetBrains製品(CLion、WebStorm、GoLand)では、"types": [ "jest", "node" ] で読み込んでたのだけど、現在の私のVSCode環境ではそれが上手くなく、 ”typeRoots" にプロジェクトローカルなパス設定となった。もちろん "types" でも方法はあるのだと思うが、こちらの方が堅い上に万一の追加パッケージに柔軟なように考えるのでいいかな。

さらに "types"では、アプリケーション本体に必要なパッケージ群で複数取り込まれていた @types/node で重複エラーが出るという謎動作が出た。パッケージ識別名で捉えるのではなくパスで誤解なく指示するのは、こちらの解決にも効いてる。

// tsconfig.jsonの現在
{
    "compilerOptions": {
        "moduleResolution": "node",
        "resolveJsonModule": true,
        "lib": [ "es6", "esnext" ],
        "module": "commonjs",
        "target": "es5",
        "sourceMap": true,
        "strict": true,
        "typeRoots": [ "./node_modules/@types" ]
    },
    "exclude": [ "node_modules" ]
}

ちなみにlambdaアプリケーションをwebpackでビルドしているので上記その他の設定です。

追記 2019/11/1

これ、Denoプラグインのせいだった。プラグイン外せばtypeRootsではなくこれまでのtypesを利用する設定でもOK。