jpskill.com
🛠️ 開発・MCP コミュニティ

code-migration

JavaScriptからTypeScriptへの変換、Reactのhooks移行、Vue 2からVue 3へのアップデートなど、フレームワークや言語、APIバージョンの異なるコードを、互換性を保ちつつ段階的に移行・現代化するSkill。

📜 元の英語説明(参考)

Migrate codebases between frameworks, languages, and API versions. Use when a user asks to convert JavaScript to TypeScript, migrate React class components to hooks, upgrade Vue 2 to Vue 3, migrate Python 2 to 3, update deprecated APIs, switch ORMs, convert Express to Fastify, or modernize legacy code. Handles incremental migration with backward compatibility.

🇯🇵 日本人クリエイター向け解説

一言でいうと

JavaScriptからTypeScriptへの変換、Reactのhooks移行、Vue 2からVue 3へのアップデートなど、フレームワークや言語、APIバージョンの異なるコードを、互換性を保ちつつ段階的に移行・現代化するSkill。

※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。

⚡ おすすめ: コマンド1行でインストール(60秒)

下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。

🍎 Mac / 🐧 Linux
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o code-migration.zip https://jpskill.com/download/14764.zip && unzip -o code-migration.zip && rm code-migration.zip
🪟 Windows (PowerShell)
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/14764.zip -OutFile "$d\code-migration.zip"; Expand-Archive "$d\code-migration.zip" -DestinationPath $d -Force; ri "$d\code-migration.zip"

完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して code-migration.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → code-migration フォルダができる
  3. 3. そのフォルダを C:\Users\あなたの名前\.claude\skills\(Win)または ~/.claude/skills/(Mac)へ移動
  4. 4. Claude Code を再起動

⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。

🎯 このSkillでできること

下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。

📦 インストール方法 (3ステップ)

  1. 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
  2. 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
  3. 3. 展開してできたフォルダを、ホームフォルダの .claude/skills/ に置く
    • · macOS / Linux: ~/.claude/skills/
    • · Windows: %USERPROFILE%\.claude\skills\

Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。

詳しい使い方ガイドを見る →
最終更新
2026-05-18
取得日時
2026-05-18
同梱ファイル
1

📖 Skill本文(日本語訳)

※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。

コード移行

概要

自動化された段階的な変換により、フレームワーク、言語、APIバージョン間でコードベースを移行します。このスキルは、JavaScriptからTypeScriptへの変換、フレームワークのアップグレード、非推奨APIの置換、ORMの移行を、機能を維持し、下位互換性を保ちながら処理します。

手順

ユーザーがコードの移行または最新化を依頼した場合、次の手順に従ってください。

ステップ 1: 移行範囲の評価

コードベースを分析して、以下を理解します。

  • ソース: 現在のフレームワーク/言語バージョン
  • ターゲット: 希望するフレームワーク/言語バージョン
  • サイズ: 影響を受けるファイル数と行数
  • 依存関係: 更新または置換が必要なライブラリ
  • リスク領域: カスタムパッチ、モンキーパッチ、またはフレームワーク内部の使用
# 影響を受けるファイルの数を数える
find src -name "*.js" | wc -l       # JS→TS 移行
grep -rl "React.Component" src/     # Class→hooks 移行
grep -rl "Vue.component" src/       # Vue 2 パターン

ステップ 2: 移行計画の作成

コードを変更する前に、移行計画を作成します。

## 移行計画: JS → TypeScript

**移行するファイル:** 47
**推定工数:** AI支援で約2時間

### フェーズ 1: セットアップ (非破壊)
- allowJs: true で tsconfig.json を追加
- TypeScript と型パッケージをインストール
- エントリーポイントの名前を .ts に変更

### フェーズ 2: 段階的な変換 (ファイルごと)
- .js → .ts/.tsx に名前を変更
- 関数シグネチャに型アノテーションを追加
- `any` を適切な型に置き換える
- 型エラーを修正

### フェーズ 3: 厳密モード
- tsconfig で strict: true を有効にする
- 残りの `any` 型を解決する
- 戻り値の型アノテーションを追加

ステップ 3: ファイルごとに移行を実行

ファイルを段階的に処理し、各変更を検証します。

JavaScript → TypeScript:

// BEFORE: src/utils/api.js
const fetchUser = async (id) => {
  const response = await fetch(`/api/users/${id}`);
  if (!response.ok) throw new Error('User not found');
  return response.json();
};
module.exports = { fetchUser };

// AFTER: src/utils/api.ts
interface User {
  id: string;
  email: string;
  name: string;
  createdAt: string;
}

export const fetchUser = async (id: string): Promise<User> => {
  const response = await fetch(`/api/users/${id}`);
  if (!response.ok) throw new Error('User not found');
  return response.json() as Promise<User>;
};

React class → hooks:

// BEFORE
class UserProfile extends React.Component {
  state = { user: null, loading: true };

  componentDidMount() {
    fetchUser(this.props.id).then(user =>
      this.setState({ user, loading: false })
    );
  }

  componentDidUpdate(prevProps) {
    if (prevProps.id !== this.props.id) {
      this.setState({ loading: true });
      fetchUser(this.props.id).then(user =>
        this.setState({ user, loading: false })
      );
    }
  }

  render() {
    if (this.state.loading) return <Spinner />;
    return <div>{this.state.user.name}</div>;
  }
}

// AFTER
function UserProfile({ id }: { id: string }) {
  const [user, setUser] = useState<User | null>(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    setLoading(true);
    fetchUser(id).then(user => {
      setUser(user);
      setLoading(false);
    });
  }, [id]);

  if (loading) return <Spinner />;
  return <div>{user?.name}</div>;
}

Vue 2 → Vue 3 (Options → Composition API):

<!-- BEFORE: Vue 2 Options API -->
<script>
export default {
  data() {
    return { count: 0, items: [] };
  },
  computed: {
    total() { return this.items.reduce((s, i) => s + i.price, 0); }
  },
  mounted() { this.fetchItems(); },
  methods: {
    async fetchItems() {
      this.items = await api.getItems();
    }
  }
};
</script>

<!-- AFTER: Vue 3 Composition API -->
<script setup lang="ts">
import { ref, computed, onMounted } from 'vue';

const count = ref(0);
const items = ref<Item[]>([]);
const total = computed(() => items.value.reduce((s, i) => s + i.price, 0));

async function fetchItems() {
  items.value = await api.getItems();
}

onMounted(fetchItems);
</script>

ステップ 4: 依存関係と構成の更新

# JS→TS の場合
npm install -D typescript @types/node @types/react
npx tsc --init

# Vue 2→3 の場合
npm install vue@3 @vue/compiler-sfc
npm uninstall vue-template-compiler

# インポートパス、ビルド構成 (vite/webpack)、およびエイリアスを更新

ステップ 5: 移行後の検証

各ファイルまたはバッチの後:

  1. 型チェッカーを実行: npx tsc --noEmit
  2. 既存のテストを実行: npm test
  3. リンターを実行: npx eslint src/
  4. プロジェクトをビルド: npm run build

エラーを報告し、続行する前に修正してください。

例 1: Express.js プロジェクトを JavaScript から TypeScript に移行する

ユーザーリクエスト: "Express アプリを JS から TS に変換してください"

実行されたアクション:

  1. プロジェクトを分析: 23 個の JS ファイル、Express 4.18、既存の型なし
  2. TypeScript、@types/express@types/nodets-node をインストール
  3. 段階的な移行のために allowJs: truetsconfig.json を作成
  4. リーフモジュール (utils、models) から始めて、ファイル名を .js.ts に変更
  5. リクエスト/レスポンスボディのインターフェースを追加
  6. requireimportmodule.exportsexport に変換
  7. ルートハンドラーに型アノテーションを追加

結果:

移行されたファイル: 23/23
修正された型エラー: 41
作成された新しいインターフェース: 8 (User, Product, Order, ApiError, etc.)
ビルド: ✅ 合格
テスト: ✅ 34/34 合格

例 2: 非推奨の React Router v5 を v6 に更新する

ユーザーリクエスト: "アプリを React Router 5 から 6 にアップグレードしてください"

実行されたアクション:

  1. React Router v5 API を使用している 12 個のファイルを特定
  2. 変換を適用:
    • <Switch><Routes>
    • <Route component={X}><Route element={<X />}>
    • useHistory()useNavigate()
    • <Redirect to="/"><Navigate to="/" replace>
    • ネストされたルートを <Outlet /> で再構築
  3. react-router-dom を v6.20 に更新

移行前/移行後:


// v5
<Switch>
  <Route exact path="/" component={Home} />
  <Route path="/use
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

Code Migration

Overview

Migrate codebases between frameworks, languages, and API versions with automated, incremental transformations. This skill handles JavaScript-to-TypeScript conversions, framework upgrades, deprecated API replacements, and ORM migrations while preserving functionality and maintaining backward compatibility.

Instructions

When a user asks to migrate or modernize their code, follow these steps:

Step 1: Assess the migration scope

Analyze the codebase to understand:

  • Source: Current framework/language version
  • Target: Desired framework/language version
  • Size: Number of files and lines affected
  • Dependencies: Libraries that need updating or replacing
  • Risk areas: Custom patches, monkey-patches, or framework internals usage
# Count affected files
find src -name "*.js" | wc -l       # JS→TS migration
grep -rl "React.Component" src/     # Class→hooks migration
grep -rl "Vue.component" src/       # Vue 2 patterns

Step 2: Create a migration plan

Before changing code, produce a migration plan:

## Migration Plan: JS → TypeScript

**Files to migrate:** 47
**Estimated effort:** ~2 hours with AI assistance

### Phase 1: Setup (non-breaking)
- Add tsconfig.json with allowJs: true
- Install TypeScript and type packages
- Rename entry point to .ts

### Phase 2: Incremental conversion (file by file)
- Rename .js → .ts/.tsx
- Add type annotations to function signatures
- Replace `any` with proper types
- Fix type errors

### Phase 3: Strict mode
- Enable strict: true in tsconfig
- Resolve remaining `any` types
- Add return type annotations

Step 3: Execute the migration file by file

Process files incrementally, verifying each change:

JavaScript → TypeScript:

// BEFORE: src/utils/api.js
const fetchUser = async (id) => {
  const response = await fetch(`/api/users/${id}`);
  if (!response.ok) throw new Error('User not found');
  return response.json();
};
module.exports = { fetchUser };

// AFTER: src/utils/api.ts
interface User {
  id: string;
  email: string;
  name: string;
  createdAt: string;
}

export const fetchUser = async (id: string): Promise<User> => {
  const response = await fetch(`/api/users/${id}`);
  if (!response.ok) throw new Error('User not found');
  return response.json() as Promise<User>;
};

React class → hooks:

// BEFORE
class UserProfile extends React.Component {
  state = { user: null, loading: true };

  componentDidMount() {
    fetchUser(this.props.id).then(user =>
      this.setState({ user, loading: false })
    );
  }

  componentDidUpdate(prevProps) {
    if (prevProps.id !== this.props.id) {
      this.setState({ loading: true });
      fetchUser(this.props.id).then(user =>
        this.setState({ user, loading: false })
      );
    }
  }

  render() {
    if (this.state.loading) return <Spinner />;
    return <div>{this.state.user.name}</div>;
  }
}

// AFTER
function UserProfile({ id }: { id: string }) {
  const [user, setUser] = useState<User | null>(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    setLoading(true);
    fetchUser(id).then(user => {
      setUser(user);
      setLoading(false);
    });
  }, [id]);

  if (loading) return <Spinner />;
  return <div>{user?.name}</div>;
}

Vue 2 → Vue 3 (Options → Composition API):

<!-- BEFORE: Vue 2 Options API -->
<script>
export default {
  data() {
    return { count: 0, items: [] };
  },
  computed: {
    total() { return this.items.reduce((s, i) => s + i.price, 0); }
  },
  mounted() { this.fetchItems(); },
  methods: {
    async fetchItems() {
      this.items = await api.getItems();
    }
  }
};
</script>

<!-- AFTER: Vue 3 Composition API -->
<script setup lang="ts">
import { ref, computed, onMounted } from 'vue';

const count = ref(0);
const items = ref<Item[]>([]);
const total = computed(() => items.value.reduce((s, i) => s + i.price, 0));

async function fetchItems() {
  items.value = await api.getItems();
}

onMounted(fetchItems);
</script>

Step 4: Update dependencies and configuration

# For JS→TS
npm install -D typescript @types/node @types/react
npx tsc --init

# For Vue 2→3
npm install vue@3 @vue/compiler-sfc
npm uninstall vue-template-compiler

# Update import paths, build config (vite/webpack), and aliases

Step 5: Verify after migration

After each file or batch:

  1. Run the type checker: npx tsc --noEmit
  2. Run existing tests: npm test
  3. Run the linter: npx eslint src/
  4. Build the project: npm run build

Report any errors and fix them before proceeding.

Examples

Example 1: Migrate an Express.js project from JavaScript to TypeScript

User request: "Convert my Express app from JS to TS"

Actions taken:

  1. Analyzed project: 23 JS files, Express 4.18, no existing types
  2. Installed TypeScript, @types/express, @types/node, ts-node
  3. Created tsconfig.json with allowJs: true for incremental migration
  4. Renamed files .js.ts starting from leaf modules (utils, models)
  5. Added interfaces for request/response bodies
  6. Converted requireimport, module.exportsexport
  7. Added type annotations to route handlers

Result:

Files migrated: 23/23
Type errors fixed: 41
New interfaces created: 8 (User, Product, Order, ApiError, etc.)
Build: ✅ passing
Tests: ✅ 34/34 passing

Example 2: Update deprecated React Router v5 to v6

User request: "Upgrade our app from React Router 5 to 6"

Actions taken:

  1. Identified 12 files using React Router v5 APIs
  2. Applied transformations:
    • <Switch><Routes>
    • <Route component={X}><Route element={<X />}>
    • useHistory()useNavigate()
    • <Redirect to="/"><Navigate to="/" replace>
    • Nested routes restructured with <Outlet />
  3. Updated react-router-dom to v6.20

Before/After:

// v5
<Switch>
  <Route exact path="/" component={Home} />
  <Route path="/users/:id" component={UserProfile} />
  <Redirect to="/" />
</Switch>

// v6
<Routes>
  <Route path="/" element={<Home />} />
  <Route path="/users/:id" element={<UserProfile />} />
  <Route path="*" element={<Navigate to="/" replace />} />
</Routes>

Result: 12 files updated, 0 type errors, all 28 tests passing.

Guidelines

  • Always migrate incrementally — one file or module at a time. Never attempt a big-bang rewrite.
  • Create the migration plan before writing any code. Share it with the user for approval on large projects.
  • For JS→TS, start with strict: false and allowJs: true, then tighten after all files are converted.
  • Preserve existing behavior exactly. Migration should not change functionality.
  • Run tests after every file migration. If tests break, fix before proceeding.
  • When migrating frameworks, check the official migration guide first (e.g., Vue 2→3, Angular upgrade guide).
  • Handle deprecated APIs by checking the library's changelog for the recommended replacement.
  • For large codebases (100+ files), suggest migrating in phases across multiple PRs.
  • Keep require/import style consistent within each file during migration — don't mix.
  • Add type annotations starting with function signatures, then variables, then generics. Don't over-type.