Closed2

tsgo 使ってみた

tkttkt

AIくんに試行錯誤の記録記事を書いてもらった

tkttkt

title: "TypeScript Native Preview (tsgo) 導入で3.4倍高速化を実現した話 - Vite設定ファイルエラーとの戦い"
emoji: "🚀"
type: "tech"
topics: ["typescript", "tsgo", "vite", "electron", "performance"]
published: true

はじめに

2025年5月23日、Microsoft TypeScriptチームから新しいGo言語実装コンパイラ「TypeScript Native Preview」(通称tsgo)が公開されました。公式発表では「最大10倍の高速化」を謳っており、大規模なElectron + Reactプロジェクトを個人開発している私も導入を検討することにしました。

この記事では、実際のプロジェクトにtsgoを導入した際の試行錯誤、遭遇した問題、そして最終的な解決方法について詳しく記録します。

対象プロジェクト

  • ElectronベースのVRChat写真管理アプリ
  • 技術スタック: Electron + React + TypeScript + Vite
  • 規模: TypeScript約20,500行、ファイル数約170個

tsgoとは

tsgoは将来的にTypeScript 7で標準となる予定の新しいコンパイラで、以下の特徴があります:

  • Go言語で実装 - ネイティブコンパイルによる高速化
  • 並行処理 - 共有メモリ並列処理の活用
  • 既存コードとの互換性 - 既存のtscと同じインターフェース

導入手順

1. パッケージのインストール

yarn add -D @typescript/native-preview

2. バージョン確認

npx tsgo -v
# Version 7.0.0-dev.20250523.1

パフォーマンス比較結果

全体の型チェック時間

まず現在のtscでの型チェック時間を測定:

time yarn lint:type-check:tsc  # tscベース
# 結果: 6.738秒

次にtsgoでの型チェック時間:

time yarn lint:type-check:tsgo  # tsgoベース  
# 結果: 1.994秒

結果: 3.4倍の高速化を実現!

詳細メトリクス比較

メインプロジェクト

メトリクス tsc tsgo 改善率
Total time 3.85s 0.765s 5.0倍高速化
Check time 2.15s 0.591s 3.6倍高速化
Memory used 504MB 533MB -5.8%

Electronプロジェクト

メトリクス tsc tsgo 改善率
Total time 1.68s 0.253s 6.6倍高速化
Check time 0.82s 0.116s 7.1倍高速化
Memory used 285MB 234MB 18%削減

公式の「10倍高速化」には及ばないものの、実用的なパフォーマンス向上を確認できました。

最初の壁: Vite設定ファイルエラー

順調に見えた導入でしたが、tsgoで型チェックを実行すると以下のエラーが発生:

electron/vite.config.ts:3:10 - error TS2305: Module '"...../node_modules/vite/index"' has no exported member 'defineConfig'.

3 import { defineConfig } from 'vite';
           ~~~~~~~~~~~~

一方、従来のtscでは同じコードが正常に動作しています。

試行錯誤1: 型インポートの削除

最初の対策として、Viteの型インポートを削除してプレーンなオブジェクトで設定を定義しました:

// 修正前(エラーになる)
import type { ConfigEnv, UserConfig } from 'vite';
export default ({ command }: ConfigEnv): UserConfig => { ... }

// 修正後(動作するが型安全性を犠牲)
export default ({ command }: { command: string }) => { ... }

これでtsgoは動作しましたが、型安全性を犠牲にするという課題が残りました。

根本原因の発見

調査を進める中で、GitHub Issues #518という重要な情報を発見しました。

tsgoの既知の制限事項

この問題はtsgoの既知の制限事項で、複雑なESM exportsフィールドを持つライブラリの型解決に問題があることが判明:

  • tsgonode_modules/vite/index を参照しようとする
  • 実際の型定義は node_modules/vite/dist/node/index にある
  • ESMの複雑な型解決エンジンがまだ完全ではない

試行錯誤2: patch-packageの検討

GitHubのIssueでは、Viteのpackage.jsonを直接修正する方法が提案されていました:

"exports": {
  ".": {
    "import": "./dist/node/index.js",
    "types": "./dist/node/index.d.ts", // ← この行を追加
    "require": "./index.cjs"
  }
}

patch-packageを使ってこの修正を適用することも検討しましたが:

  • node_modulesの変更が必要
  • チームメンバーとの共有が複雑
  • Viteのバージョンアップ時の影響

これらの理由で断念しました。

最終解決: exclude方式

最終的に採用したのは、Vite設定ファイルをtsgoの型チェック対象から除外する方法でした。

設定変更

// tsconfig.json
{
  "exclude": [
    "node_modules",
    "**/*.spec.ts",
    "**/*.spec.tsx",
    "**/*.test.ts", 
    "**/*.test.tsx",
    "vite.config.ts",          // 追加
    "electron/vite.config.ts"  // 追加
  ]
}
// electron/tsconfig.json
{
  "exclude": ["node_modules", "**/*.spec.*", "**/*.test.*", "vite.config.ts"]
}

Vite設定ファイルを元の形式に復元

// 型安全性を復活
import { defineConfig } from 'vite';
import type { ConfigEnv, UserConfig } from 'vite';

export default ({ command }: ConfigEnv): UserConfig => {
  // 型安全な設定
};

最終的なワークフロー

package.jsonの設定

{
  "scripts": {
    // 標準(tsgo使用)- 日常開発用
    "lint": "biome check . && lint:type-check",
    "lint:type-check": "lint:type-check:tsgo",
    
    // 完全チェック(tsc使用)- Vite設定含む
    "lint:type-check:tsc": "tsc --noEmit && tsc --noEmit -p electron",
    
    // tsgo専用
    "lint:type-check:tsgo": "tsgo --noEmit && tsgo --noEmit -p electron"
  }
}

型チェック戦略

コマンド 実行時間 対象 用途
yarn lint (tsgo) 1.994秒 Vite設定以外 日常開発 - 高速
yarn lint:type-check:tsc 6.738秒 全ファイル 完全チェック

メリット・デメリット

メリット ✅

  • 高速化: 3.4倍の型チェック高速化
  • 型安全性: Vite設定ファイルの型安全性を維持
  • シンプル: node_modulesの変更不要
  • 保守性: Viteのバージョンアップの影響なし

デメリット ⚠️

  • 設定分離: Vite設定ファイルは別途tscでチェック必要
  • プレビュー版: 他のライブラリでも同様の問題が発生する可能性

学び・今後の展望

tsgoの現状

  • パフォーマンス: 確実に高速化を実現
  • 互換性: ESM複雑な型解決に一部制限あり
  • 実用性: 適切な回避策で実用可能

プロジェクトへの影響

個人開発では以下の効果を実感:

  • 開発サイクル短縮: 型チェック待ち時間の大幅削減
  • 生産性向上: 3.4倍高速化により、よりアジャイルな開発が可能
  • メモリ効率: 特にElectronプロジェクトで21%のメモリ削減

まとめ

tsgoの導入は一筋縄ではいかない部分もありましたが、最終的に以下を実現できました:

  1. 3.4倍の型チェック高速化
  2. 型安全性の完全維持
  3. 実用的な開発ワークフロー

TypeScript 7でtsgoが標準になることを考えると、今回の経験は貴重な先行投資となりました。ESMライブラリとの互換性問題は今後改善されることが期待されますが、現時点でも適切な回避策により実用レベルで活用できることが分かりました。

参考リンク

このスクラップは3ヶ月前にクローズされました