こんにちは。チームのコードレビューをしていて、「また `undefined` のプロパティを読みに行こうとして画面が真っ白になってるよ……」と頭を抱えた経験、君にもないかい?
中級から一歩進んでシニアの領域に足を踏み入れようとしている君なら、JavaScriptのダイナミックさ、つまり「何でも書けちゃう自由度の高さ」が、時として巨大なコードベースにおける凶器に変わることを肌で感じているはずだ。
「TypeScriptを導入したいけれど、ビルドパイプラインの変更コストや、チームの学習コストを考えると今すぐには踏み切れない……」
そんなジレンマを抱える現場の救世主が、今回解説する `jsconfig.json` と `checkJs` だ。TypeScriptのコンパイラ(`tsc`)の力を借りて、JSファイルのままで静的型チェックの恩恵を受けるための極上のノウハウを授けよう。
—
なぜ、今「プレーンなJavaScript」に型が必要なのか?
JavaScriptは、変数の型をRuntime(実行時)まで決定しない。`typeof` や `instanceof` を駆使して防御的コードを書くのはプロの基本だが、人間はうっかりミスをする生き物だ。
// よくある現場の悲劇
function calculateTotal(item) {
// item.price が文字列の “1000” だったり、最悪 undefined だったりする
return item.price 1.1;
}
ブラウザのJavaScriptエンジン(V8など)は、このコードを動かすために裏側で必死に型の推論やインラインキャッシュの最適化を行っているが、「開発者が意図した型」までは保証してくれない。結果、本番環境で `TypeError: Cannot read properties of undefined` が爆誕する。
「じゃあTypeScriptに書き換えようぜ」と言いたいところだが、既存の数万行のJSを移行するのは大仕事だ。そこで、VS Codeの裏側で動いているTypeScript言語サービス(Language Service)に、JSのままで厳格な監視をさせようというのが今回のテーマだ。
—
`jsconfig.json` でVS Codeを目覚めさせる
プロジェクトのルートディレクトリに `jsconfig.json` を1つ置くだけで、そのディレクトリ配下のVS Codeの振る舞いが劇的に変わる。まずは実務で即座に使える決定版のファイルを作ろう。
実践的な `jsconfig.json` の設定
プロジェクトのルートに `jsconfig.json` を作成し、以下のように設定してほしい。
{
“compilerOptions”: {
“target”: “es2022”,
“module”: “esnext”,
“checkJs”: true, // ★ここが今回の主役!JSファイルに対する型チェックを有効化
“strict”: true, // 厳格な型チェックをすべて有効化(null安全など)
“noEmit”: true, // 型チェックのみを行い、JSファイルをコンパイル出力しない
“baseUrl”: “.”,
“paths”: {
“@/”: [“src/”] // 現場で必須の絶対パス エイリアス設定
}
},
“include”: [
“src//” // src配下のすべてのJSを監視対象にする
],
“exclude”: [
“node_modules”,
“dist”
]
}
この設定をした瞬間から、VS Codeのエディタ上でTypeScriptと同等の赤波線(型エラー)が表示されるようになる。ビルド環境を一切汚さず、エディタの機能だけで型安全を手に入れられるというわけだ。
—
JSDocを制する者は、`checkJs` を制する
`”checkJs”: true` にすると、当然ながらこれまで許されていた「適当なコード」に対してVS Codeが怒り出す。しかし、JavaScriptにはTypeScriptのような静的な型定義構文(`function foo(x: number)` など)は書けない。
ここで登場するのが JSDoc だ。JavaScriptのコメント構文でありながら、TypeScriptのコンパイラはこれを「立派な型定義」として解釈する。
実務で使えるJSDoc型注釈のサンプル
以下のコードを、`checkJs: true` を有効にしたプロジェクトの `.js` ファイルに貼り付けてみてほしい。エディタがどう反応するか、すぐに分かるはずだ。
// src/services/paymentService.js
/
- @typedef {Object} User
- @property {string} id – ユーザーID
- @property {string} name – ユーザー名
- @property {number} 日付未入力 – 年齢(オプショナル)
/
/
- 支払い金額を計算する関数
- @param {User} user – 対象のユーザー情報
- @param {number} baseAmount – 基本料金
- @returns {number} 最終的な支払い金額(税込み)
/
export function calculatePayment(user, baseAmount) {
// 万が一、baseAmountに文字列が渡されたらVS Codeが即座に赤波線で警告してくれる
const taxRate = 0.1;
// user.id が存在することもJSDocのおかげで補完が効く
console.log(`Calculating for user: ${user.name}`);
return baseAmount (1 + taxRate);
}
// — 使用例 —
const myUser = {
id: “u-001”,
name: “Yamada Taro”
};
// 正しい使い方
const total = calculatePayment(myUser, 5000);
// 【型エラーの例】第二引数に文字列を渡すと、エディタが怒ってくれる!
// const errorTotal = calculatePayment(myUser, “5000”);
このように、JSDocを書くことで、JSDoc自体が優れたコードドキュメントになりつつ、TypeScriptの型安全の恩恵を100%受けることができる。
—
既存の巨大なコードベースに導入する際の「現場の知見」
さて、ここからがシニアの腕の見せ所だ。
すでに数年運用されている大規模なJSプロジェクトにいきなり `”checkJs”: true` を入れるとどうなるか? エディタ中が真っ赤になり、開発者がパニックを起こして逃げ出す。
段階的に導入するための、現場で使える現実的なアプローチを伝授しよう。
1. 最初は厳格すぎない設定から始める
プロジェクト全体にいきなり `strict: true` を適用するのはハードルが高い。まずは以下のように緩めの設定から始め、徐々に厳しくしていくのが定石だ。
{
“compilerOptions”: {
“checkJs”: true,
“strict”: false, // 最初はfalse
“noImplicitAny”: false // 暗黙のanyを許容する
}
}
2. どうしても型エラーを無視したい場合の奥の手
サードパーティの古いライブラリや、どうしても型が合わないレガシーなロジックに直面したときは、ファイルの先頭(または該当行の直前)に以下のコメントを挿入すれば、TypeScriptの魔の手(型チェック)から逃れることができる。
// @ts-nocheck
// このファイル全体の型チェックを無効化する(レガシーコードの緊急避難用)
特定の1行だけをスルーしたい場合はこちら。
// @ts-ignore
const legacyResult = oldLibraryFunctionThatReturnsAnything();
※ただし、`@ts-ignore` の乱用はコードベースの腐敗を招く。「なぜ型が合わないのか」をコメントに残すか、JSDocで型を正しく定義し直すのがプロとしてのプライドだ。
—
まとめ:明日からチームのコード品質を一段引き上げるために
JavaScriptの柔軟性を保ったまま、TypeScriptの堅牢性を手に入れる `jsconfig.json` + `checkJs` のアプローチは、リプレイスの予算が出ない現場や、段階的に型安全な文化を根付かせたいチームにとって最強の武器になる。
明日出社したら、まずはチームのメインプロジェクトのルートに `jsconfig.json` を置き、`”checkJs”: true` を設定してみよう。きっと、今まで見過ごされていた無数の潜在バグの卵が赤波線として浮かび上がり、君のコードレビューの負担を劇的に減らしてくれるはずだ。
さあ、エディタを開いて、ワンランク上のJavaScript開発を始めようぜ。

コメント