🦙

tsconfig.json の extends の使い方

2021/03/29に公開

解決したい問題

今回お題にしているのは、Nuxtですが、それに限らないと思います。
アプリを作るにあたって、Nuxtでフロントエンドを作り、APIを作成して呼び出し、APIがDBの読み書きをする、という構成にすることが多いのではないかと思います。
そしてこの各サービスをまとめて開発する場合、それぞれをDockerイメージにしたい場合もあるのではないかと思います。
例えば、このような構成です。

XXXApp
├── docker-compose.yml 
├── .git
├── .gitignore
├── README.md
├── xxx-app-api
│   ├── (Django REST)
│       ├── ...
├── xxx-app-db
│   ├── (postgres)
│       ├── ...
├── xxx-app-web
│   ├── (nuxt)
│       ├── ...

この構成を、まとめて開発するので、一つのVSCodeでXXXAppを開きたいと考えます。

そして、Nuxtについては、今時はやはりTypescriptで開発したいなと思います。

ところが、うまく参照ができない。

例えば、pages/todolist.vueというものを作って、

pages/todolist.vue
<script lang="ts">
import { defineComponent, reactive, computed } from '@vue/composition-api'
import { TodoStore } from '~/store'

・・・

    const todos = TodoStore
    const todolist = computed(() => todos.getTodos)

みたいに書く際に、getTodosで補完が効いて欲しいのですが、「from '~/store'」のところで、「Cannot find module」エラーと言われてしまうわけです。

これの解消に時間がかかりました。意外と、ズバッと教えてくれる情報がないなと。

構成に関わらず必須な作業

まず、shims-vue.d.ts の対応、tsconfig.json への「files」「include」対応は必要です。
例えば、下記の情報など参照。
Nuxt 2.8の生成するtsconfig.jsonを使うとIntelliJ(WebStorm、PhpStorm等)がCannot find moduleエラーを吐く

そして、元々記述はされていると思いますが、

XXXApp/xxx-app-web/tsconfig.json
    "baseUrl": ".",
    "paths": {
      "~/*": [
        "./*"
      ],
      "@/*": [
        "./*"
      ]
    },

も必要です。

Typescriptプロジェクトが下位階層にある場合

ところが、最初に問題意識を書いたような階層構成の場合は、これだけでは足りません。
上記構成で言うと、VSCodeとしては、XXXApp が基礎となる位置になるわけで、そこに tsconfig.json はいません。アプリ動作のためには、xxx-app-web にいる必要があるのですが、VSCodeにとっては、XXXApp にいて欲しいわけです。
そこで、extends を使います。

・・・という情報までは辿り着きましたが、それの意味が理解できなかった。

XXXApp/tsconfig.json
{
  "extends": "./poli-link-web/poli-link/tsconfig.json"
}

これだけ書いても、そのまま読み込むだけなので、その場所が基礎位置になるだけです。
そこに store はいません。

extends なので、それを読み込むだけではダメなのです。
そこから見た基礎位置を、baseUrl として指定します。

XXXApp/tsconfig.json
{
  "extends": "./xxx-app-web/tsconfig.json",
  "compilerOptions": {
    "baseUrl": "./xxx-app-web",
  }
}

これが必要です。これによって、VSCodeとしても位置が整合することになるので、import が正しく機能することになります。

分かってしまえば、当然だね、と思いますが、修行中の身には堪えました。

以上です。

Discussion