25
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

TypeScript 7が来た。tscに77秒かかっていたVS Codeが7.5秒になった現実

25
Posted at

この記事の対象読者

  • TypeScriptで開発している方(規模を問わず)
  • 「tscが遅い」と感じたことがある方
  • TypeScript 6 / 7 への移行をそろそろ考えなければいけない方
  • 「なぜGoで書き直したの?」が気になる方

この記事で得られること

  • TypeScript 7(Project Corsa / tsgo)が何をどう変えたのかが理解できる
  • 公式ベンチマーク結果の正しい読み方がわかる
  • strict-by-defaultで既存コードが何箇所壊れるかの実態がわかる
  • 今すぐ試す方法本格移行のロードマップがわかる

この記事で扱わないこと

  • Go言語自体の文法や特徴の解説
  • TypeScriptの型システムの基礎(型注釈、ジェネリクスなど)
  • Deno / BunとのランタイムTS実行の比較

1. 「嘘だろ」と声に出た日

正直に告白する。TypeScript 7のベンチマークを初めて見たとき、「嘘だろ」と声に出した。

VS Codeのコードベース(150万行)のフルビルド:

  • tsc(TypeScript 5.x): 77〜89秒
  • tsgo(TypeScript 7): 7.5〜8.74秒

10倍速い。文字通りの10倍。

これはマーケティング用の誇張ではない。Microsoftの公式ブログに掲載された、実際のプロジェクトで測定されたデータだ。しかもVS Codeだけじゃない。

プロジェクト tsc(従来) tsgo(TS 7) 高速化倍率
VS Code(150万行) 89.11秒 8.74秒 10.2x
Sentry 133.08秒 16.25秒 8.2x
言語サービス起動 9.6秒 1.2秒 8.0x

「ビルドの間にコーヒーを入れに行く」という開発者あるあるが、もう成立しない時代が来ている。

ここまでで、TypeScript 7のインパクトが伝わっただろうか。次は、この記事で使う用語を整理しておこう。


2. 前提知識の確認

本題に入る前に、この記事で登場するキーワードを整理しておく。

2.1 Project Corsa(プロジェクト・コルサ)とは

TypeScriptコンパイラをGo言語で完全リライトするプロジェクトのコードネーム。「Corsa」はイタリア語で「レース/走行」を意味する。ちなみに従来のTypeScriptコンパイラのコードネームは「Strada」(イタリア語で「道」)。道を走っていた時代からレースの時代へ、というネーミングだ。

2.2 tsgo とは

TypeScript 7のコマンドラインツール名。従来のtscに代わるもの。Go言語で書かれたネイティブバイナリで、Node.jsを必要としない。最終的にはtscにリネームされてtypescriptパッケージに統合される予定。

2.3 TypeScript 6.0 とは

TypeScript 7への「橋渡しリリース」として設計されたバージョン。JavaScriptベースの最後のTypeScriptであり、6.1は計画されていない。7.0で削除される設定を事前に非推奨(deprecated)にすることで、移行を段階的に行えるようにしている。2026年2月にbetaリリース済み。

2.4 Strada API / Corsa API

Stradaは従来のTypeScript(5.x/6.0)が公開しているプログラムAPI。ESLintやPrettierなどのツールがこのAPIに依存している。TypeScript 7ではStrada APIがサポートされず、新しいCorsa APIに移行する必要がある。

これらの用語が押さえられたら、なぜGoで書き直したのか、その背景を見ていこう。


3. なぜGoで書き直したのか — TypeScript 14年目の決断

3.1 JavaScriptの壁

TypeScriptコンパイラはTypeScript自身で書かれていた(いわゆるセルフホスティング)。しかし、Node.js上で動作するJavaScriptには構造的な限界がある:

  • シングルスレッド: マルチコアCPUの恩恵を受けられない
  • GC(ガベージコレクション)の停止: 大量のオブジェクトを扱うと、GCのポーズが無視できない
  • メモリ効率: JavaScriptオブジェクトのオーバーヘッドが大きい

150万行のVS Codeをビルドするのに89秒。100万行超のモノレポでCI/CDが10分以上。これが「TypeScriptは大規模で遅い」という評判につながっていた。

3.2 なぜRustではなくGoなのか

「なぜRustじゃないの?」という疑問は当然出る。TypeScriptチームが挙げた理由:

観点 Go Rust
コンパイル速度 秒単位で完了 分〜時間単位
ランタイム速度 十分に高速 若干高速だが差は僅差
メモリ管理 GC(自動) 所有権モデル(手動的)
学習コスト TypeScriptチームにとって低い 高い(所有権の概念が独特)
並行処理 goroutineが自然 async/awaitは複雑
実績 esbuild(Go)で10-100x高速化を実証済み SWC(Rust)で20-70x高速化を実証済み

最終的に「パフォーマンステストで両言語は誤差の範囲だった」とされ、開発生産性の高いGoが選ばれた。

3.3 「書き直しは失敗する」というジンクス

ソフトウェアの世界で「ゼロからの書き直し」は鬼門とされてきた。しかしMicrosoftのTypeScriptチームは、2025年5月のtsgoアルファ公開からわずか半年で、20,000件のコンパイラテストケースのうち6,000件のエラー検出テストで、74件を除いてすべて一致という驚異的な互換性を達成した。

Daniel Rosenwasser(TypeScript PM)の言葉を借りれば:

「多くの開発者にとって書き直しプロジェクトは、リリースされるまで完全に机上の空論かもしれません。ここではそうではありません。」

背景がわかったところで、基本的な仕組みを見ていこう。


4. 基本概念と仕組み

4.1 何が変わって、何が変わらないのか

変わったこと(内部アーキテクチャ):

項目 従来(tsc / Strada) TypeScript 7(tsgo / Corsa)
実装言語 TypeScript(Node.js上で実行) Go(ネイティブバイナリ)
スレッドモデル シングルスレッド マルチスレッド(goroutine)
メモリ管理 V8 GC Go GC(より効率的)
言語サービスプロトコル TSServer(独自プロトコル) LSP(Language Server Protocol)
API Strada API Corsa API(開発中)

変わらないこと(開発者体験):

項目 状況
TypeScriptの文法 完全に同じ
出力されるJavaScript 同一(ターゲットが同じなら)
tsconfig.jsonの書き方 ほぼ同じ(一部デフォルト値変更あり)
エディタのTypeScript体験 同じ(ただしLSP経由に変更)

4.2 strict-by-default — 最大の破壊的変更

TypeScript 7(および移行用のTypeScript 6)では、strict: trueがデフォルトになる。

これまでstrictを明示的に有効にしていなかったプロジェクトは、アップグレードした瞬間に大量のエラーが出る。

// TypeScript 5.x  デフォルトではstrictはfalse
{
  "compilerOptions": {
    "target": "es2020"
    // strict を書いていない = false
  }
}
// TypeScript 6.0 / 7.0  strictがデフォルトでtrue
{
  "compilerOptions": {
    "target": "es2025"
    // strict を書いていない = true  ここが変わる
  }
}

strict: true は以下のフラグを全て有効にする:
noImplicitAny, strictNullChecks, strictFunctionTypes, strictBindCallApply, strictPropertyInitialization, noImplicitThis, alwaysStrict

特に noImplicitAnystrictNullChecks は、大量のエラーを引き起こす可能性が高い。

4.3 その他の破壊的変更

変更内容 影響度 詳細
target: "es5" 削除 最低ターゲットが es2015 に。IE対応コードはBabel等で別途変換が必要
baseUrl 非推奨 パスマッピングは paths で明示的に指定する
moduleResolution: "node10" 削除 nodenext または bundler に移行
module: "amd" / "umd" / "systemjs" 削除 ESモジュールに統一
outFile 削除 バンドラー(Vite, webpack等)を使用
esModuleInterop: false 不可 安全なインターポップが常時有効に
Strada API 非サポート ツール開発者向け サードパーティツールの対応待ちが必要
JSDoc @enum / @constructor 削除 JSプロジェクト向け TypeScript構文への移行を推奨

基本概念が理解できたところで、実際にtsgoを動かしてみよう。


5. 実践:tsgoを動かしてみよう

5.1 インストール

# TypeScript 7(tsgo)のプレビュー版をインストール
npm install -D @typescript/native-preview

# バージョン確認
npx tsgo -v
# Version 7.0.0-dev.xxxxx(ビルドによって異なる)

2026年3月現在、@typescript/native-previewはnightly更新されている。CIで使う場合はバージョンを固定することを推奨。

5.2 環境別の設定ファイル

開発環境用(tsconfig.json)— TypeScript 7対応

{
  "compilerOptions": {
    "target": "es2025",
    "module": "nodenext",
    "moduleResolution": "nodenext",
    "strict": true,
    "noEmit": true,
    "skipLibCheck": true,
    "isolatedModules": true,
    "verbatimModuleSyntax": true,
    "paths": {
      "@app/*": ["./src/app/*"],
      "@lib/*": ["./src/lib/*"]
    }
  },
  "include": ["src/**/*.ts"],
  "exclude": ["node_modules", "dist"]
}

本番ビルド用(tsconfig.build.json)— JS出力が必要な場合

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "noEmit": false,
    "outDir": "./dist",
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true
  },
  "include": ["src/**/*.ts"],
  "exclude": ["node_modules", "dist", "tests", "**/*.test.ts"]
}

CI/移行検証用(tsconfig.tsgo.json)— tsgoとtscの並行実行

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

5.3 既存プロジェクトでの検証手順

# Step 1: まずTypeScript 6.0 beta でdeprecation警告を確認
npm install -D typescript@beta
npx tsc --noEmit
# → deprecated な設定があればここで警告が出る

# Step 2: ts5to6 ツールでtsconfig.jsonを自動修正
npx @andrewbranch/ts5to6 --fixBaseUrl tsconfig.json
npx @andrewbranch/ts5to6 --fixRootDir tsconfig.json

# Step 3: tsgo でビルド検証
npm install -D @typescript/native-preview
npx tsgo --noEmit
# → エラーがなければ移行準備OK

# Step 4: ベンチマーク比較
npx tsc --noEmit --extendedDiagnostics
npx tsgo --noEmit --extendedDiagnostics
# → Total time を比較して速度改善を確認

5.4 VS Codeでtsgoを使う

# VS Code Marketplaceから「TypeScript Native Preview」拡張をインストール
# または、.vscode/settings.json に以下を追加:
{
  "typescript.experimental.useTsgo": true
}

Native Preview拡張はまだ一部の言語サービス機能が未実装の場合がある。問題が発生したら TypeScript Native Preview: Disable コマンドで一時的に無効化できる。

5.5 package.jsonスクリプトの設定

{
  "scripts": {
    "typecheck": "tsgo --noEmit",
    "typecheck:legacy": "tsc --noEmit",
    "build": "tsgo --build",
    "build:legacy": "tsc --build",
    "dev": "node --watch src/index.ts",
    "lint": "eslint src/",
    "ci:check": "tsgo --noEmit && eslint src/"
  },
  "devDependencies": {
    "@typescript/native-preview": "latest",
    "typescript": "^6.0.0"
  }
}

5.6 実行結果の例

$ npx tsgo --noEmit --extendedDiagnostics

Files:            423
Lines:            98241
Identifiers:      112893
Symbols:          67451
Types:            28934
Instantiations:   45123
Memory used:      89234K
Parse time:       0.089s
Bind time:        0.021s
Check time:       0.834s
Emit time:        0.000s
Total time:       0.952s

# 同じプロジェクトをtscで:
$ npx tsc --noEmit --extendedDiagnostics
# ...
Total time:       8.234s

約10万行のプロジェクトで8.2秒 → 0.95秒。8.7倍の高速化。

5.7 よくあるエラーと対処法

エラー / 警告 原因 対処法
Option 'baseUrl' is deprecated TypeScript 7で削除される設定 npx @andrewbranch/ts5to6 --fixBaseUrl tsconfig.json で自動修正
Option 'target' value 'es5' is deprecated ES5ターゲット廃止 targetes2015以上に変更
Parameter 'x' implicitly has an 'any' type strict: trueによりnoImplicitAnyが有効化 型注釈を追加するか、一時的にstrict: falseを明示
Object is possibly 'null' strictNullChecksが有効化 null チェックを追加(if (obj !== null)
Module resolution 'node10' is deprecated node10解決アルゴリズム廃止 moduleResolutionnodenextに変更
ツールが動かない(ESLint等) Strada APIがtsgoで非サポート tsc 6.0を並行インストールし、ツール向けに使い分ける

5.8 環境診断スクリプト

// check-ts7-readiness.ts
// 実行: node check-ts7-readiness.ts(Node.js v22.18+でType Stripping対応)

import { execSync } from 'child_process';
import { readFileSync, existsSync } from 'fs';

function checkReadiness(): void {
  const issues: string[] = [];
  const warnings: string[] = [];

  // tsconfig.json の確認
  if (!existsSync('tsconfig.json')) {
    issues.push('tsconfig.json が見つかりません');
  } else {
    const tsconfig = JSON.parse(readFileSync('tsconfig.json', 'utf-8'));
    const opts = tsconfig.compilerOptions ?? {};

    if (opts.target?.toLowerCase() === 'es5' || opts.target?.toLowerCase() === 'es3') {
      issues.push(`target: "${opts.target}" は TypeScript 7 で削除されます → es2015以上に変更`);
    }
    if (opts.baseUrl) {
      warnings.push(`baseUrl: "${opts.baseUrl}" は非推奨 → paths で明示的に指定`);
    }
    if (opts.moduleResolution === 'node' || opts.moduleResolution === 'node10') {
      issues.push(`moduleResolution: "${opts.moduleResolution}" は削除 → "nodenext" に変更`);
    }
    if (opts.module === 'amd' || opts.module === 'umd' || opts.module === 'systemjs') {
      issues.push(`module: "${opts.module}" は削除 → ESモジュールに移行`);
    }
    if (opts.strict === false) {
      warnings.push('strict: false → TypeScript 7 ではデフォルトが true になります');
    }
    if (opts.outFile) {
      issues.push('outFile は削除 → バンドラー(Vite等)を使用');
    }
  }

  // tsgo の有無
  try {
    const ver = execSync('npx tsgo -v 2>/dev/null', { encoding: 'utf-8' }).trim();
    console.log(`tsgo: ${ver}`);
  } catch {
    warnings.push('tsgo がインストールされていません → npm install -D @typescript/native-preview');
  }

  // 結果出力
  if (issues.length > 0) {
    console.log('\n❌ TypeScript 7 で壊れる設定:');
    for (const issue of issues) console.log(`  - ${issue}`);
  }
  if (warnings.length > 0) {
    console.log('\n⚠️ 推奨される変更:');
    for (const w of warnings) console.log(`  - ${w}`);
  }
  if (issues.length === 0 && warnings.length === 0) {
    console.log('\n✅ TypeScript 7 移行の準備ができています');
  }
}

checkReadiness();

実装方法がわかったので、次は具体的なユースケースを見ていこう。


6. ユースケース別ガイド

6.1 ユースケース1: 大規模モノレポのCI/CD高速化

想定読者: 100万行超のモノレポでCI/CDパイプラインのビルド時間に悩んでいるチーム

推奨構成: tsgoを型チェック専用に使い、JS出力はesbuild / Viteに任せる

サンプルコード(GitHub Actions):

# .github/workflows/typecheck.yml
name: Type Check (tsgo)

on: [push, pull_request]

jobs:
  typecheck:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '22'

      - name: Install dependencies
        run: npm ci

      - name: Type check with tsgo
        run: npx tsgo --build --noEmit

      - name: Lint
        run: npx eslint src/

tsgo --buildはプロジェクト参照(project references)に対応しているため、モノレポ内の複数パッケージを並列で型チェックできる。

6.2 ユースケース2: strict移行を段階的に進める

想定読者: strict: falseの状態で長年運用してきたプロジェクトのリーダー

推奨構成: ディレクトリ単位でstrictを段階的に有効化

サンプルコード:

// tsconfig.json(プロジェクトルート  一旦strictをfalseで維持)
{
  "compilerOptions": {
    "target": "es2025",
    "module": "nodenext",
    "strict": false,
    "ignoreDeprecations": "6.0"
  }
}
// src/new-modules/tsconfig.json(新規モジュールはstrictで開始)
{
  "extends": "../../tsconfig.json",
  "compilerOptions": {
    "strict": true
  },
  "include": ["./**/*.ts"]
}
// strict: true 環境下で書くコード(型安全)
interface ApiResponse<T> {
  data: T | null;  // null許容を明示
  error: string | null;
}

function processResponse<T>(response: ApiResponse<T>): T {
  if (response.error !== null) {
    throw new Error(response.error);
  }
  if (response.data === null) {
    throw new Error('Unexpected null data');
  }
  return response.data;  // ここでTに確定
}

6.3 ユースケース3: baseUrl廃止への対応

想定読者: baseUrlpathsでパスエイリアスを設定しているプロジェクト(NestJS等でよくある構成)

推奨構成: ts5to6ツールで自動変換 + paths の明示的指定

サンプルコード:

//  Before(TypeScript 5.x  baseUrl使用)
{
  "compilerOptions": {
    "baseUrl": "./src",
    "paths": {
      "@app/*": ["app/*"],
      "@lib/*": ["lib/*"]
    }
  }
}
//  After(TypeScript 7 対応  baseUrl不要)
{
  "compilerOptions": {
    "paths": {
      "@app/*": ["./src/app/*"],
      "@lib/*": ["./src/lib/*"]
    }
  }
}
# 自動変換ツール
npx @andrewbranch/ts5to6 --fixBaseUrl tsconfig.json

ユースケースを把握できたところで、この先の学習パスを確認しよう。


7. 学習ロードマップ

この記事を読んだ後、次のステップとして以下をおすすめする。

初級者向け(まずはここから)

  1. TypeScript公式: Progress on TypeScript 7 - December 2025 — 公式ブログで現状を把握
  2. npm install -D @typescript/native-preview でtsgoをインストールし、手元のプロジェクトで npx tsgo --noEmit を実行してみる
  3. VS Codeの「TypeScript Native Preview」拡張をインストールしてエディタ体験を試す

中級者向け(実践に進む)

  1. TypeScript 6.0 betaをインストールして、deprecation警告を確認する
  2. ts5to6ツールでtsconfig.jsonを自動修正する
  3. CI/CDパイプラインでtsgoとtscを並行実行し、結果の差分を検証する
  4. strict: trueを有効にして、エラー数を把握 → 段階的に修正

上級者向け(さらに深く)

  1. TypeScript-Go GitHubリポジトリ — Corsa実装のソースコードを読む
  2. Corsa APIの設計を追い、自社ツールの移行計画を立てる
  3. tsgoの--extendedDiagnosticsでプロジェクト内のボトルネックを特定し、型の複雑度を最適化する

8. まとめ

この記事では、TypeScript 7(Project Corsa / tsgo)について以下を解説した:

  1. GoリライトによりフルビルドがVS Codeで10.2倍、Sentryで8.2倍速くなった — メモリ使用量も約50%削減
  2. TypeScript 6.0は「橋渡しリリース」 — 6.1は存在しない。7.0で削除される設定を事前に非推奨にする
  3. strict-by-defaultが最大の破壊的変更 — 加えてES5ターゲット廃止、baseUrl非推奨、AMD/UMD削除など
  4. 今すぐtsgoを試せる@typescript/native-previewで型チェック、VS Code拡張でエディタ体験

私の所感

TypeScriptの歴史の中で、これは間違いなく最大の転換点だ。

2012年のリリース以来、TypeScriptは「JavaScriptの上に型を載せる」というアプローチで成長してきた。そのコンパイラ自身もTypeScript/JavaScriptで書かれていた。それが14年目にして、コンパイラだけがGoに移行する。「TypeScriptはTypeScriptで書くべきだ」という美学よりも、「開発者の生産性を最大化する」という実利が勝った。

個人的に最も嬉しいのは、エディタのIntelliSenseが高速化されることだ。大規模プロジェクトで型推論の結果表示に数秒かかっていたあの待ち時間が、1秒未満になる。コンパイル速度よりも、この**「エディタの反応速度」が日常の開発体験を根本から変える**と確信している。

一方で、Strada APIの非サポートは短期的に痛い。ESLintやPrettier等のツールエコシステムが追いつくまで、tsc 6.0とtsgoを並行運用する期間が生じる。この「二重管理の期間」をどれだけ短くできるかが、エコシステム全体の課題だ。

TypeScript 7は「待つ」のではなく「今試す」フェーズにある。tsgoをインストールして、自分のプロジェクトがどれだけ速くなるか、まず測ってみてほしい。


参考文献


この記事が役に立ったら、いいねとストックをお願いします。

X: https://x.com/geneLab_999

25
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
25
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?