TypeScript 6.0 Stable移行でNext.js 16.2 CI回帰を防ぐ

TypeScript 6.0へ上げたいけど、Next.js 16.2でmoduleResolutionbaseUrlまわりが崩れそうで不安、という人に向けて書きました。この記事を読むと、tsconfigをどこから直すか、CIでどう再発を止めるかまで一気に整理できます。僕は福祉事業のIT全般を担当しながら、複業でAI×SaaS開発も回しているので、複数案件を止めない移行手順として実務ベースでまとめます。

こんな方におすすめ

  • TypeScript 6.0 Stable 移行を進めたいが、設定差分の洗い出しに時間がかかっている方
  • Next.js 16.2 moduleResolution baseUrl の警告やエラーで手が止まった方
  • tsconfig CI 回帰テストを導入して、再発防止まで仕組み化したい方
  • 非エンジニアメンバーにも説明できる移行手順を作りたい方

この記事でわかること

  • 2026年3月時点のTypeScript/Next.jsの最新状況(RC/Stable差分)
  • moduleResolutionbaseUrlでつまずく根本原因
  • 壊さず進めるtsconfig修正手順と、実運用向けの分割戦略
  • GitHub Actionsで回すCI回帰テストのテンプレート

公開前確認(2026年5月時点):TypeScript移行では公式ドキュメントのProject ConfigurationとModules Referenceを基準に、baseUrlや古いmoduleResolutionをCIで検出し、Next.js側のサポート範囲も同時に確認してください。

僕は福祉事業のIT全般を担当しつつ、フリーランスでTypeScript/Next.js案件を並行しています。現場で「動くけど不安な設定」を何度も見てきたので、今回も“今日から使える形”で書きます。

TypeScript 6.0移行で最初に押さえる事実(2026年3月時点)

まず日付をそろえておきます。TypeScript公式ブログでは、2026年3月6日に「TypeScript 6.0 RC」が公開されています。つまり2026年3月27日時点では、確認できる公式アナウンスはRCが最新です。一方でNext.jsは、2026年3月18日に16.23月20日に16.2.1が出ています。

  • 2026-03-06 — TypeScript 6.0 RC公開(移行用の非互換整理が本格化)
  • 2026-03-18 — Next.js 16.2公開(開発体験と性能改善が中心)
  • 2026-03-20 — Next.js 16.2.1公開(バグ修正のバックポート)
  • 2026-03-24以降 — 16.2.1 canaryでTS6関連の修正が継続投入

ここで大事なのは、「TS側の非推奨化」と「Next側の追随タイミング」はズレるという点です。イメージとしては、道路工事(TypeScript)が先に始まって、信号制御(Next.js)が順次アップデートされる感じです。だからこそ、単純なバージョンアップではなく、設定ファイルとCIをセットで更新するのが現実的です。

Next.js 16.2でmoduleResolution/baseUrlが問題化する理由

問題の芯は2つです。1つ目は、TypeScript 6.0 RCでmoduleResolution: node(実質node10)が非推奨寄りになったことです。2つ目は、baseUrlの扱いが見直され、以前の“なんとなく解決”が通らなくなったことです。公式のmoduleResolutionドキュメントでも、node10は現代用途では通常不要と明記されています。

さらに、Next.js側でも以前から課題化していて、Issue #82017ではmoduleResolutionnodeに寄せる挙動が議論されています。16.2.1 stableのリリースノートには「canaryの全変更は含まれない」と明記があり、canary側には「deprecated TS node10 defaults回避」「TS6 baseUrl deprecation修正(extended tsconfig)」が入っています。つまり、stable運用中のプロジェクトほど自前で守りを作る必要があります。

項目 旧来のよくある設定 TS 6.0移行時のリスク 推奨方針
moduleResolution node 非推奨警告・将来破綻 Nextアプリはbundler、Node実行はnodenext
baseUrl "./src"で曖昧解決 意図しない解決先が混入 pathsに明示プレフィックス移行
extends構成 親で共通化しすぎ 子設定で警告が再発 runtime別にtsconfigを分離
CIチェック next buildのみ 設定回帰を検知しにくい tsc --noEmit+設定検証スクリプト

つまり、エラーは「Next.jsが悪い」ではなく、tsconfigの世代差分が露出した結果です。 ここを理解すると、対処が一気にシンプルになります。

tsconfigを壊さず直す手順(baseUrl撤去とpaths再定義)

ここは手順でいきます。まずは現状把握、次に置換、最後に用途別分割です。難しそうに見えますが、やることは3ステップです。

  1. 解決後設定を可視化npx tsc --showConfig > .tmp/tsconfig.resolved.jsonで、extends後の実態を確認します。
  2. baseUrl依存を除去baseUrlを消し、paths側へ明示プレフィックスを寄せます。
  3. runtimeで分離 — Web側はmoduleResolution: "bundler"、Nodeスクリプト側は"nodenext"に分けます。
// before (よくある形)
{
  "compilerOptions": {
    "baseUrl": "./src",
    "paths": {
      "@app/*": ["app/*"],
      "@lib/*": ["lib/*"]
    },
    "moduleResolution": "node"
  }
}

// after (TS6移行向け)
{
  "compilerOptions": {
    "paths": {
      "@app/*": ["./src/app/*"],
      "@lib/*": ["./src/lib/*"]
    },
    "moduleResolution": "bundler"
  }
}

モノレポなら、さらに分けると安全です。tsconfig.app.jsonbundlertsconfig.scripts.jsonnodenextという形です。baseUrlの公式説明にも、設計意図と現在の推奨が整理されています。

つまずきやすいポイント

  • 親tsconfigだけ直して安心 — 子で上書きされて再発しやすいです
  • pathsの先頭./を省略 — 環境差で解決結果がぶれやすいです
  • rootDir未指定のまま — TS6系では意図外の出力構造になることがあります

「baseUrlを消すだけ」では不十分で、pathsを“実パス前提”に作り直すのがコツです。

tsconfig CI 回帰テストを作る(GitHub Actions実装例)

次は再発防止です。Next.js公式ドキュメントでも、CIでtsc --noEmitを別途回す運用が推奨されています。つまり、next buildだけでは守り切れません。ここは「型チェック」と「設定チェック」を分離すると安定します。

name: tsconfig-regression
on:
  pull_request:
  workflow_dispatch:

jobs:
  verify:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node: [20, 22]
        next_channel: ["16.2.1", "canary"]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node }}
      - run: npm ci
      - run: npm i -D next@${{ matrix.next_channel }} typescript@rc
      - run: npx tsc -p tsconfig.json --noEmit
      - run: node scripts/check-tsconfig.mjs
      - run: npx next build
// scripts/check-tsconfig.mjs
import { execSync } from "node:child_process";

const raw = execSync("npx tsc --showConfig", { encoding: "utf8" });
const cfg = JSON.parse(raw);
const c = cfg.compilerOptions ?? {};
const errors = [];

if (c.moduleResolution  "node" || c.moduleResolution  "node10") {
  errors.push("moduleResolution=node/node10 はNG");
}
if ("baseUrl" in c) {
  errors.push("baseUrl が残っています");
}

if (errors.length) {
  console.error(errors.join("\\n"));
  process.exit(1);
}

この形にしておくと、「誰かが古いテンプレをコピペして戻す」事故をPR段階で止められます。CIは“正しさを証明する場所”より、“戻り事故を止めるゲート”として設計すると運用が軽くなります。

運用メモとして、外部導線ではなく、実測ログ・設定差分・再現手順を同じ場所に残してチーム内で確認できる形にしてください。

stableとcanaryをどう使い分けるか(実務の判断基準)

最後に運用設計です。Next.js 16.2.1 stableはバグ修正中心で、canaryの全変更は入りません。なので「本番はstable固定、検証だけcanary追従」が現実的です。ここを曖昧にすると、毎回の障害対応で方針論争になりがちです。

レーン 依存バージョン 目的 昇格条件
production Next.js 16.2.1固定 安定運用 週次CIが連続通過
migration Next.js canary + TS6系 先行検証 deprecationゼロ・build成功
release-prep TS 6.0 stable確定版 本番反映前最終確認 2環境以上で再現確認

「とりあえずlatest」は短期では速いですが、複業や小規模チームほど後で重くなります。 逆にこの3レーンを作ると、非エンジニアにも「どこまでが実験か」を説明しやすくなります。

関連テーマとして、Node.js側のTypeScript実行基盤を整理した記事も置いています。CIを軽くしたい方は Node.js 22のType Stripping実践ガイド も合わせて読むと設計がつながりやすいです。

運用メモとして、外部導線ではなく、実測ログ・設定差分・再現手順を同じ場所に残してチーム内で確認できる形にしてください。

この移行を先送りしたチームで起きやすい3つの損失

設定移行を後回しにすると、機能開発よりも“調査の時間”が増える可能性があります。 具体的には、①PRごとに断続的な型警告が出てレビュー速度が落ちる、②環境ごとに解決結果がズレて再現確認に時間がかかる、③担当者しか直せない属人運用になる、の3つです。知らないままだと、半年後に「小さな不整合の総量」がチームの生産性を削る形になりやすいです。

この記事を書いている理由

僕自身、SESから人材教育、そして福祉領域のIT担当へキャリアを移してきました。550名以上のキャリア面談をやってきた経験もあって、技術の正しさだけじゃなく「伝わる運用設計」が本当に大事だと感じています。実務でも、業務効率化ツールで月80時間の工数削減を出したときは、派手な新機能より設定の再現性を整えた効果が大きかったです。だからこそ、今回も“知っている人だけ得する設定差分”を、実装まで落として共有したいと思っています。

次のアクション

運用メモとして、外部導線ではなく、実測ログ・設定差分・再現手順を同じ場所に残してチーム内で確認できる形にしてください。

今日からできるアクション

  • 30分で棚卸しnpx tsc --showConfigmoduleResolutionbaseUrlを確認
  • 1日で実装pathsを実パスへ書き換え、runtime別tsconfigへ分割
  • 翌日から再発防止 — CIにtsc --noEmitと設定検証スクリプトを追加
  • 回遊強化 — 関連記事の Type Strippingガイド も確認して開発基盤をそろえる