💭

VSCodeでホバー時のTypeScriptの型ヒントをすべて表示する

2024/10/17に公開
6

はじめに

こんにちは、からころです。
今回は、VSCode でホバー時の TypeScript の型ヒントをすべて表示する方法について書いていこうと思います。

※ 投稿日の 2024/10/17 から 2024/10/28 ごろに仕様が変わり、defaultMaximumTruncationLengthの書き換えだけでは、動作しなくなりましたので修正版を公開しています。

デフォルトの設定では型の情報量が増えると型が省略される

VSCode では、TypeScript を利用して開発する際に、ホバーすると以下のように型ヒントを表示することができます。

しかし、デフォルトの設定のままでは、下記のようにプロパティ数が多くなると型ヒントが省略されてしまいます。

上記の解決方法を以下で説明していこうと思います。

tsconfig.json に noErrorTruncation:true を追加する?

情報として、tsconfig.json に noErrorTruncation:true を追加するという記事がよく検索にヒットします。これは果たして本当なのでしょうか?

ドキュメントによると、noErrorTruncation は、エラー時の型データが省略されるのを防止することができそうです。
https://www.typescriptlang.org/tsconfig/#noErrorTruncation

これはこれで必要そうですが、エラー時ではないので今回のパターンの原因は別の箇所にありそうですね。

型ヒントが省略される直接の原因

直接の原因ですが、VSCode が管理する TypeScript 用の言語サーバで参照されているデフォルトの表示上限が160行で固定されているためです。

また、このデフォルト上限を変更するための、API は VSCode では提供されていないので、settings.json をこねくり回しても解決しません。厄介ですね...。

解決方法

下記のスクリプトを Node.js で走らせることで解決します。

実行例
# node changeTypeScriptHover.js <path-to-vscode> <max-length>
node changeTypeScriptHover.js ~/.vscode 1000

具体的には、VSCode 上で動作する TypeScript の言語サーバが参照するファイル群の、
defaultMaximumTruncationLengthnoTruncationMaximumTruncationLength に設定する値を直接書き換えています。

changeTypeScriptHintLength.js
const fs = require('fs')
const args = process.argv

if (4 < args.length || args.length < 3) {
  console.error('Usage: node changeTypeScriptHover.js <path-to-vscode> <max-length>')
  console.error('Example: node changeTypeScriptHover.js ~/.vscode 160')
  process.exit(1)
}

if (isNaN(Number(args[3]))) {
  console.error('max-length should be a number')
  process.exit(1)
}

const targetPath = args[2]
const maxLength = args[3] || 160

console.log(`targetPath: ${targetPath}, maxLength: ${maxLength}`)

const targetDirs = fs.readdirSync(`${targetPath}/extensions`, 'utf-8')
  .filter(dir => dir.includes('vscode-typescript'))
  .map(name => `${targetPath}/extensions/${name}/node_modules/typescript/lib`)

console.log('found targetDirs', targetDirs)

targetDirs.forEach(targetDir => {
  const fileDirs = fs.readdirSync(targetDir, 'utf-8').map(name => `${targetDir}/${name}`)
  fileDirs.forEach(fileDir => {
    if (fileDir.endsWith('.js')) {
      const content = fs.readFileSync(fileDir, 'utf-8')
      if (!content.includes('defaultMaximumTruncationLength = ') || !content.includes('noTruncationMaximumTruncationLength = ')) {
        return
      }
      console.log(`find! ${fileDir}`)
      const replaced1 = content.replace(/defaultMaximumTruncationLength = \d+/g, `defaultMaximumTruncationLength = ${maxLength}`)
      const replaced2 = replaced1.replace(/noTruncationMaximumTruncationLength = \d+/g, `noTruncationMaximumTruncationLength = ${maxLength}`)
      try {
        fs.writeFileSync(fileDir, replaced2, {
          encoding: 'utf-8',
        })
        console.log(`write success!`)
      } catch (e) {
        console.error(`write failed! ${e}`)
      }
    }
  })
})

おわりに

今回は、VSCode でホバー時の TypeScript の型ヒントをすべて表示する方法について書きました。
質問やスクリプトに不備などありましたらコメントお願いします!!

Discussion

junerjuner

issues だと ここらへんで言われている話ですね。

https://github.com/microsoft/TypeScript/issues/35601

からころ / karacoroからころ / karacoro

issueでは、tsserver.jstypescript.js を変えればいいと書いてあるんですが、実際にはそれだと動作しないんですよね。(アップデートでファイル名が変わったりしてます)
なので、モンキーパッチを当てることでその辺がアップデートで変わっても問題ないように工夫してたりします!

melodycluemelodyclue

VSCode が管理する TypeScript 用の言語サーバで参照されているデフォルトの表示上限が160行で固定されているため

これはパフォーマンス向上のためなんですかね?

というのも、解決方法に書いてあることをすることでVSCodeが重くなるのかなーなんて思いました!

からころ / karacoroからころ / karacoro

おそらくパフォーマンスのためではないでしょうし、重くなるってほど重くはならないと思います。むしろ、extensionsを使う方が重くなります。そこまでたくさんの型を表示することは少ないという想定だったのかもしれません…が真相は把握できてないです。ちなみに表示行数を増やせるようになるように、issueで現在進行形で議論されています。

付け加えて、extensionsを使えばよくない?みたいな話もなくないですが、悪意のあるコードのインジェクションリスクから導入したくない場合があるためこの方法が必要な場合があります。