Nuxt 4では、TypeScriptの設定方式が大きく変わりました。従来の単一ファイル継承(extends)から、TypeScript公式のプロジェクト参照(Project References)方式へ移行しています。

この変更により、サーバーコードの型がクライアント側に漏れる「型漏れ(Type-bleed)」問題が解消され、IDE補完の精度やビルドパフォーマンスも向上しています。

ただし移行時には「extends行を消し忘れて130件超の型エラーが出る」「vue-tsc-bフラグを付け忘れる」など、ドキュメントだけでは気づきにくい落とし穴も存在します。

本記事では、Nuxt 4のtsconfig設定を体系的に整理し、移行から運用まで必要な知識をまとめています。

Nuxt 3のtsconfig方式が抱えていた課題

Nuxt 3では、npx nuxt prepareを実行すると.nuxt/tsconfig.jsonが1つだけ生成され、ルートのtsconfig.jsonからextendsで継承する仕組みでした。

// Nuxt 3 のルート tsconfig.json
{
  "extends": "./.nuxt/tsconfig.json",
  "compilerOptions": {
    "strict": true
  }
}

この方式にはいくつかの問題があります。

型漏れ(Type-bleed)の発生

単一のtsconfigでプロジェクト全体を管理するため、サーバー専用のNode.js APIの型(fspathなど)がクライアント側のVueコンポーネントでも参照可能になります。

具体的には、server/utils/に定義したサーバー専用ユーティリティをクライアント側のコンポーネントでimportしても、TypeScriptが型エラーを出しません。ビルド時やランタイムで初めてエラーに気づくことになります。

IDEの補完精度の低下

すべてのコンテキスト(app・server・shared)の型が1つのtsconfigに混在するため、Vueコンポーネントの編集時にサーバー専用のAPIが補完候補に表示されるなど、不要な候補が増加します。

ビルドの非効率

tsconfig全体を毎回パースするため、変更のあったコンテキストだけを再コンパイルする最適化が効きません。大規模プロジェクトではビルド時間への影響が顕著になります。

Nuxt 4のプロジェクト参照方式

Nuxt 4では、TypeScript公式のProject References機能を採用し、コンテキストごとに独立したtsconfigファイルを自動生成します。

新しいルートtsconfig.jsonの構成

{
  "files": [],
  "references": [
    { "path": "./.nuxt/tsconfig.app.json" },
    { "path": "./.nuxt/tsconfig.server.json" },
    { "path": "./.nuxt/tsconfig.shared.json" },
    { "path": "./.nuxt/tsconfig.node.json" }
  ]
}

"files": []は、ルートtsconfig自体がコードをコンパイルするのではなく、参照先に処理を委譲する宣言です。この方式はTypeScript公式が推奨するプロジェクト参照のパターンに準拠しています。

4つの生成ファイルと役割

npx nuxt prepareを実行すると、.nuxt/配下に4つのtsconfig(+後方互換用の1つ)が自動生成されます。

ファイル対象コード主な用途
tsconfig.app.jsonapp/ディレクトリVueコンポーネント、composables、pages、layouts
tsconfig.server.jsonserver/ディレクトリNitroサーバー、APIルート、サーバーミドルウェア
tsconfig.shared.jsonshared/ディレクトリapp・server両方で使う型定義やユーティリティ
tsconfig.node.jsonビルド設定ファイルnuxt.config.ts、カスタムモジュール
tsconfig.json(レガシー)全体後方互換用。将来のバージョンで削除予定

各ファイルにはコンテキスト固有の設定が含まれます。tsconfig.app.jsonにはVue関連の型参照やauto-importの定義が、tsconfig.server.jsonにはNitroのAPIルート型やNode.js固有の型が設定されます。

この分離により、サーバー側のfspathをクライアント側でimportするとTypeScriptが型エラーを報告するようになります。

プロジェクト参照がもたらす利点

TypeScript公式のProject References機能を使うことで、以下のメリットが得られます。

  • 型の分離: コンテキストをまたいだ不正な型参照をコンパイル時に検出
  • 選択的再コンパイル: 変更のあったコンテキストだけをリビルド
  • IDE性能の向上: 各コンテキストに適した補完候補のみを表示
  • 依存関係の明示: コンテキスト間の依存がファイル構造として可視化

Nuxt 3からの移行手順

移行はオプトイン方式です。既存のextends方式を使い続けることも可能ですが、型安全性とIDE体験の向上のためにプロジェクト参照方式への移行を推奨します。

Step 1: extends行の削除とreferencesへの書き換え

まず、ルートのtsconfig.jsonを書き換えます。

移行前(Nuxt 3):

{
  "extends": "./.nuxt/tsconfig.json",
  "compilerOptions": {
    "strict": true
  }
}

移行後(Nuxt 4):

{
  "files": [],
  "references": [
    { "path": "./.nuxt/tsconfig.app.json" },
    { "path": "./.nuxt/tsconfig.server.json" },
    { "path": "./.nuxt/tsconfig.shared.json" },
    { "path": "./.nuxt/tsconfig.node.json" }
  ]
}

重要: extends行を必ず削除してください。 Nuxt 4のsolution-style tsconfig構成("files": [] + referencesのみで構成するパターン)では、従来の"extends": "./.nuxt/tsconfig.json"と共存させることができません。extendsを残したままだと、130件以上の型エラーが発生したり、Vue Language Serverがクラッシュする報告がGitHub Issue #33481 で挙げられています。

Step 2: 手動で作成したserver/tsconfig.jsonの削除

Nuxt 3でserver/tsconfig.jsonを手動作成していた場合は削除します。Nuxt 4では.nuxt/tsconfig.server.jsonが自動生成されるため、手動ファイルは不要です。

rm server/tsconfig.json

Step 3: nuxt prepareの実行

.nuxt/配下にプロジェクト参照用のtsconfigファイルを生成します。

npx nuxt prepare

Step 4: 型チェックスクリプトの更新

package.jsonのtypecheckスクリプトに-bフラグを追加します。プロジェクト参照方式ではTypeScriptのビルドモード(-b)が必須です。

{
  "scripts": {
-   "typecheck": "nuxt prepare && vue-tsc --noEmit"
+   "typecheck": "nuxt prepare && vue-tsc -b --noEmit"
  }
}

-bフラグを付けないと、referencesの解決が行われず型チェックが正しく動作しません。

Step 5: 型定義ファイルの配置先を移動

Nuxt 4のプロジェクト参照方式では、型拡張(Type Augmentation)ファイルの配置場所が制限されます。

型定義の種類配置先ディレクトリ
アプリ側の型拡張app/
サーバー側の型拡張server/
共有型定義shared/

app/server/shared/以外に配置した.d.tsファイルはプロジェクト参照方式では認識されません。Nuxt 3でプロジェクトルートに置いていたtypes/ディレクトリなどは、用途に応じて適切なディレクトリに移動してください。

Step 6: CI/CDパイプラインの更新

CI環境のスクリプトも同様にtypecheckコマンドを更新します。-bフラグの追加と、nuxt prepareによるtsconfig生成が実行されていることを確認してください。

nuxt.config.tsでのTypeScript設定カスタマイズ

Nuxt 4では、生成されるtsconfigファイルをnuxt.config.ts経由でカスタマイズできます。.nuxt/配下のファイルを直接編集するのは避けてください。nuxt prepareで上書きされます。

各コンテキストの設定箇所

export default defineNuxtConfig({
  typescript: {
    // app側の tsconfig.app.json をカスタマイズ
    tsConfig: {
      compilerOptions: {
        noUncheckedIndexedAccess: true,
        exactOptionalPropertyTypes: true,
      },
    },
    // shared側の tsconfig.shared.json をカスタマイズ
    sharedTsConfig: {
      // ...
    },
    // node側の tsconfig.node.json をカスタマイズ
    nodeTsConfig: {
      // ...
    },
  },
  nitro: {
    typescript: {
      // server側の tsconfig.server.json をカスタマイズ
      tsConfig: {
        // ...
      },
    },
  },
})

注意点として、サーバー側のtsconfigはtypescript.serverTsConfigではなくnitro.typescript.tsConfigで設定します。NitroがNuxt外のサーバーエンジンとして独立しているためです。

推奨のcompilerOptions

型安全性を高めるために、以下のオプションの有効化を検討してください。

export default defineNuxtConfig({
  typescript: {
    strict: true, // デフォルトはtypeCheck有効時にtrue
    typeCheck: true,
    tsConfig: {
      compilerOptions: {
        noUncheckedIndexedAccess: true,
        // 配列やオブジェクトのインデックスアクセスに
        // undefined チェックを強制
      },
    },
  },
})

noUncheckedIndexedAccessは、Record型やオブジェクトのブラケットアクセスでundefinedの可能性を型レベルで検出します。ランタイムのTypeError: Cannot read properties of undefinedを防ぐのに有効です。

compatibilityVersionによる段階的移行

一括移行が難しい場合、compatibilityVersion: 4を設定した上で個別の機能フラグを制御する段階的移行が可能です。

export default defineNuxtConfig({
  compatibilityVersion: 4,
  future: {
    // 各フラグをfalse(v3互換)に設定し、
    // 1つずつtrueに切り替えて検証する
  },
  experimental: {
    // ...
  },
})

STORESのエンジニアチームが採用した方式では、compatibilityVersion: 4を設定した後、すべてのフラグを一旦OFF(v3互換)にし、1つずつ有効化して動作確認を進めています。この方法なら、tsconfig関連の変更だけを先に適用し、データフェッチやディレクトリ構造の変更は後から対応するといった順序付けが可能です。

よくあるエラーと対処法

130件以上の型エラーが突然発生する

原因: extends行を残したままプロジェクト参照を追加している。

対処: ルートのtsconfig.jsonから"extends": "./.nuxt/tsconfig.json"を削除します。Nuxt 4のsolution-style構成ではextendsreferencesを同じtsconfigに共存させることができません。

IDE(VSCode / WebStorm)で型補完が効かない

原因1: npx nuxt prepareが未実行で、.nuxt/tsconfig.*.jsonが存在しない。

npx nuxt prepare

原因2: IDEがプロジェクト参照方式を認識していない。VSCodeの場合、TypeScript 5.0以降が必要です。Cmd+Shift+P → “TypeScript: Select TypeScript Version” でワークスペースのTypeScriptバージョンを確認してください。

原因3: WebStormの場合、Vue Language Serverのバージョンが古い可能性があります。WebStormを最新版に更新し、TypeScriptサービスを再起動してください。

カスタム.d.tsファイルが認識されない

原因: プロジェクト参照方式では、app/server/shared/以外のディレクトリに置いた型定義ファイルは自動で読み込まれません。

対処: 型定義ファイルをコンテキストに応じた適切なディレクトリに移動します。

# 移行前
types/
  nuxtSchema.d.ts
  global.d.ts

# 移行後(用途に応じて振り分け)
app/types/
  global.d.ts
shared/types/
  nuxtSchema.d.ts

あるいは、nuxt.config.tstypescript.tsConfig.includeで明示的にパスを追加する方法もあります。

export default defineNuxtConfig({
  typescript: {
    tsConfig: {
      include: ['../types/*.d.ts'],
      // パスは .nuxt/tsconfig.app.json からの相対パス
    },
  },
})

nuxt.config.tsでauto-importが使えない

原因: nuxt.config.tstsconfig.node.jsonのコンテキストで処理されるため、Nuxtのauto-import(refcomputeduseRuntimeConfigなど)は利用できません。

対処: nuxt.config.tsでは明示的にimport文を記述してください。これはNuxt 4で意図的に導入された制約で、設定ファイルの型安全性を高めるためのものです。

サーバー側の型がクライアント側に漏れる(意図的な共有が必要な場合)

対処: shared/ディレクトリを使います。shared/に配置したコードはapp・server両方のコンテキストから参照可能です。

shared/
  types/
    api.ts    # APIレスポンスの型定義(app・server共通)
  utils/
    validate.ts  # バリデーションロジック(app・server共通)

海外の移行事例に学ぶ実践知見

米国の技術ブログでは、プロダクション環境での移行事例が報告されています。

ビルドパフォーマンスの改善

Simform Engineeringのエンジニアが認証・マルチテナンシー対応のプロダクションアプリをNuxt 3→4に移行した事例では、以下の改善が記録されています。

指標Nuxt 3Nuxt 4改善率
クライアントビルド8.2秒5.54秒32%短縮
サーバービルド5.1秒3.49秒31%短縮
バンドルサイズ950KB741KB22%削減

出典: Simform Engineering - Medium

これはNuxt公式のベンチマークではなく個別のプロダクション環境での計測値ですが、tsconfigのプロジェクト参照による選択的再コンパイルを含む複数の最適化が改善に寄与しています。

移行時に頻出する追加エラーパターン

海外の事例報告では、tsconfig以外にも以下のパターンが頻出しています。

データフェッチのデフォルト値変更:

// Nuxt 3: error.value の型は Error | null
// Nuxt 4: error.value の型は Error | undefined
if (error.value === null) { /* Nuxt 3 */ }
if (error.value === undefined) { /* Nuxt 4 */ }
// 推奨: 両方に対応する書き方
if (!error.value) { /* Nuxt 3/4 両対応 */ }

shallowRefへの変更:

Nuxt 4ではuseFetch/useAsyncDatadataがデフォルトでshallowRefになります。ネストしたオブジェクトのリアクティビティが必要な場合はdeep: trueを明示指定します。

const { data } = await useFetch('/api/items', {
  deep: true, // Nuxt 3と同じdeep reactivityを維持
})

tsconfig参照ファイルの数の違いに関する補足

海外記事の中には、tsconfig.app.jsontsconfig.server.jsonの2つだけを参照する構成が掲載されているケースがあります。Nuxt 4の正式なリリースでは4つのファイル(app、server、shared、node)が生成されるため、公式ドキュメントの構成に従って4つすべてを参照してください。

@tsconfig/nuxtパッケージとの関係

npmには@tsconfig/nuxtというパッケージが公開されています。これはNuxt向けの推奨tsconfig設定を提供する外部パッケージですが、Nuxt 4が自動生成するtsconfigとは別物です。

Nuxt 4では.nuxt/配下に最適化されたtsconfigが自動生成されるため、@tsconfig/nuxtパッケージを追加でインストールする必要はありません。混同しないよう注意してください。

まとめ

Nuxt 4のtsconfig設定で押さえるべきポイントを整理します。

基本構成:

  • ルートのtsconfig.jsonreferences方式で4つの生成ファイルを参照する
  • .nuxt/配下のtsconfig.app.jsontsconfig.server.jsontsconfig.shared.jsontsconfig.node.jsonがコンテキストごとの型定義を担当する
  • カスタマイズはnuxt.config.ts経由で行い、生成ファイルを直接編集しない

移行のチェックリスト:

  • extends行を削除してからreferencesを追加する(共存不可)
  • vue-tscのコマンドに-bフラグを追加する
  • 型定義ファイルをapp/server/shared/に移動する
  • server/tsconfig.jsonを手動作成していた場合は削除する
  • npx nuxt prepareで生成ファイルを更新する

トラブル時の確認事項:

  • npx nuxt prepareが実行済みか
  • extends行が残っていないか
  • IDEのTypeScriptバージョンが5.0以上か
  • .d.tsファイルが適切なディレクトリに配置されているか