1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【VSCode / Vue】 Move to file が Vue プロジェクトで落ちる問題をTypeScriptを1行パッチして回避する

Last updated at Posted at 2025-11-16

Move to file の動作イメージはこちら(公式ドキュメント)
https://code.visualstudio.com/updates/v1_82#_move-to-file-refactoring

VSCode で TypeScript のリファクタ機能「Move to file」をVueプロジェクトで実行すると、
クラッシュして動作しないという問題があります。

TypeScript Server Error (5.9.3) Debug Failure. 
File xxx.vue has unknown extension. 
Error: Debug Failure.

Move to file を実行すると VSCode 右下にこのようなエラーが表示されます。

この記事では、TypeScript 本体に 1行パッチ を当てることで Move to file を動作させる方法を紹介します。

node_modules 配下の編集は本来避けるべきですが、
影響範囲が非常に限定的に修正可能であり、この機能が使えるかどうかでリファクタコストが大幅に変わると思うので記事にしてみました。

本記事で紹介する内容は TypeScript に公式修正が入るまでの暫定的な回避策です。
影響範囲は限定的ですが、パッチの内容を理解したうえで適用することを推奨します。

結論(最短で知りたい人向け)

node_modules/typescript/lib/typescript.js を次のように修正します。
typescript5.9.3では 153916 行目あたりです。

// 153908行目(typescript 5.9.3の場合)
function getMoveToRefactoringFileSuggestions(fileName, positionOrRange, preferences = emptyOptions) {
    // ...
    const files = mapDefined(allFiles, (file) => {
-     const fileNameExtension = extensionFromPath(file.fileName);
+     const fileNameExtension = tryGetExtensionFromPath2(file.fileName);
+     if (fileNameExtension === void 0) return;
      const isValidSourceFile = !(program == null ? void 0 : program.isSourceFileFromExternalLibrary(sourceFile)) && !(sourceFile === getValidSourceFile(file.fileName) || extension === ".ts" /* Ts */ && fileNameExtension === ".d.ts" /* Dts */ || extension === ".d.ts" /* Dts */ && startsWith(getBaseFileName(file.fileName), "lib.") && fileNameExtension === ".d.ts" /* Dts */);
      return isValidSourceFile && (extension === fileNameExtension || (extension === ".tsx" /* Tsx */ && fileNameExtension === ".ts" /* Ts */ || extension === ".jsx" /* Jsx */ && fileNameExtension === ".js" /* Js */) && !toMoveContainsJsx) ? file.fileName : void 0;
    });
    return { newFileName: createNewFileName(sourceFile, program, host, toMove), files };
  }

これで

  • .ts.ts の Move は正常動作
  • .vue の import 自動書き換えも成功

という期待通りの動作をしてくれるようになります。

Move to file とは

VSCode + TypeScript で利用できるリファクタリング機能です。
変数名などにカーソルを置き、右クリック→リファクター→ Move to file から利用できます。
次のような機能を提供します。

  • 変数 / 関数 / 型などを他ファイルに安全に移動
  • 元ファイルは自動的に import に置き換え
  • 参照しているすべてのファイルの import 文を書き換える

詳しくは https://code.visualstudio.com/updates/v1_82#_move-to-file-refactoring を参照してください。

Move to file を利用したことがない方はぜひ利用してみてください!
リファクタのコストが大きく下がります。

該当Issue

TypeScript 側の修正で解決するはずですが執筆時点では未修正の状態です。

動作確認環境

  • TypeScript: 5.9.3
  • VSCode の Vue Official 拡張機能: 3.1.4

解決方法(詳しく)

1. Move to file が落ちることを確認する

適当な .ts の変数を右クリック → リファクター → Move to file
Vue プロジェクトではここで落ちます。

VSCode 右下のエラーメッセージ → 詳細表示 で、次のようなスタックトレースが見えるはずです。

File <project root>/ComponentA.vue has unknown extension.
at extensionFromPath (<project root>/node_modules/typescript/lib/typescript.js:22738:39)
at <project root>/node_modules/typescript/lib/typescript.js:153916:33
at mapDefined (<project root>/node_modules/typescript/lib/typescript.js:2606:22)

このメッセージから node_modules の TypeScript が利用されているか、VSCode標準の TypeScript が利用されているかがわかるはずです。

2. VSCode が「ワークスペースの TypeScript」を使っているか確認

VSCode 下側のステータスバーで TypeScript バージョンを確認し、

  • ワークスペースのバージョンを使用

を選びます。

もしくは .vscode/settings.json に直接設定してもOKです。

{
  "typescript.tsdk": "node_modules/typescript/lib"
}

これをしないとパッチした TypeScript が使われず効果がでません。

3. TypeScript 本体(typescript.js)を patch

node_modules/typescript/lib/typescript.js を開き次のように修正します。
結論(最短で知りたい人向け)のdiffと同様の内容です)

// 153908行目(typescript 5.9.3の場合)
function getMoveToRefactoringFileSuggestions(fileName, positionOrRange, preferences = emptyOptions) {
    // ...
    const files = mapDefined(allFiles, (file) => {
-     const fileNameExtension = extensionFromPath(file.fileName);
+     const fileNameExtension = tryGetExtensionFromPath2(file.fileName);
+     if (fileNameExtension === void 0) return;
      const isValidSourceFile = !(program == null ? void 0 : program.isSourceFileFromExternalLibrary(sourceFile)) && !(sourceFile === getValidSourceFile(file.fileName) || extension === ".ts" /* Ts */ && fileNameExtension === ".d.ts" /* Dts */ || extension === ".d.ts" /* Dts */ && startsWith(getBaseFileName(file.fileName), "lib.") && fileNameExtension === ".d.ts" /* Dts */);
      return isValidSourceFile && (extension === fileNameExtension || (extension === ".tsx" /* Tsx */ && fileNameExtension === ".ts" /* Ts */ || extension === ".jsx" /* Jsx */ && fileNameExtension === ".js" /* Js */) && !toMoveContainsJsx) ? file.fileName : void 0;
    });
    return { newFileName: createNewFileName(sourceFile, program, host, toMove), files };
  }

ポイントは、

  • extensionFromPath をやめて
  • extensionFromPath が内部で利用している tryGetExtensionFromPath を直接呼ぶことで Debug.fail() が実行されないようにする
  • 未知拡張子(.vue)の場合は return でスキップ

という処理にすることです。

4. VSCode を再起動

TypeScript サービスがパッチ版を読み込みます。
忘れず再起動してください。

5. Move to file が正常動作するか確認

次を確認し、問題なければパッチ成功です!

  • a.ts に定義した変数を b.ts へ Move to file すると問題なく移動できる
  • その変数を参照している .vue ファイルの import も自動で書き換えられる

(任意だが推奨)patch-package で差分を管理する

本編は以上ですが、TypeScript を更新しパッチが消えてしまうことに備えての補足もしておきます。
node_modules/typescript/lib/typescript.js に加えた修正は patch-package で管理しておくと安全です。

# パッチファイル作成 (プロジェクトに `patches/typescript+5.9.3.patch` のようなファイルが作成されます)
npx patch-package typescript

# パッチを適用 (作成されたパッチが `node_modules/typescript/lib/typescript.js` に適用される)
npx patch-package

パッチファイルが作成されるので、どのような変更をしたか git で管理できます。
個人でパッチするだけなら stash するか、.git/info/exclude に追記するなどして、パッチファイルが git で共有されないようにしておけばいいと思います。
また、patch-package 公式では postinstall 時にパッチを自動実行するようにしていますが、Move to file 用パッチだけであればそこまでしなくていいと思います。

まとめ

  • Vue + TypeScript で Move To File が落ちるのは TS 本体の未修正バグ
  • TypeScript の getMoveToRefactoringFileSuggestions に1行パッチで回避可能
  • .vue 側の import 書き換えも Volar が自動対応
  • patch-package で安定運用できる
  • TypeScript の公式修正が入るまでの一時的な回避策
1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?