やあ。最近、プロダクトの規模が少しずつ大きくなってきて、型がないバニラなJavaScriptの海で溺れそうになっていないかい?「TypeScriptを導入したいけれど、ビルドパイプラインをいじる余裕がない」「レガシーなスクリプト資産が多すぎて、一気に移行するのはリスキーすぎる」……そんな現場の叫びを、シニアの私は毎日のように聞いているよ。
でも、安心してほしい。TypeScriptという「重厚長大なお城」を今すぐ建てなくとも、JSDoc(ジェイズドック)という強力な秘密兵器を使えば、今日の明日からVSCodeなどのエディタの補完と静的解析の恩恵をフルに受けることができるんだ。
今日は、TypeScript導入前の現実解であり、モダンなJS開発の隠し味でもある「JSDocを用いた型定義の基礎」について、現場のリアルな知見を交えて徹底的に解説しよう。
—
なぜ、今さらJSDocなのか?
「JavaScriptにコメントを書くだけで型チェックができる」と言われても、最初は半信半疑かもしれないね。「どうせコメントなんて誰も読まないし、コードを修正したときに書き忘れて嘘のコメントになるだけだろ」と。
だが、現代のエディタ(VSCodeやWebStorm)の言語サーバー(tsserver)は、JSDocを単なる「人間向けのメモ」としては見ていない。「コードの仕様書(型定義)」として解釈し、リアルタイムで赤波線を引いてくれる。つまり、JSDocを書くことは、JavaScriptのままでTypeScriptと同等の型安全性を手に入れることに他ならないんだ。
ブラウザのエンジン自体はJSDocを完全に無視するので、トランスパイラを通さずにそのままブラウザで動かせるという、バニラJSならではの軽快さを維持できるのも大きなメリットだね。
—
1. 基本のキ:`@type` でプリミティブとオブジェクトを縛る
まずは基本中の基本、変数の型を明示する `@type` タグから見ていこう。
現場でよくある「何のデータが入ってくるか分からない設定オブジェクト」を例にするよ。
/
- ユーザーの設定情報を管理するモジュール
/
/
- ユーザー名の文字列
- @type {string}
/
let userName = “Yamada Taro”;
// うっかり数値を入れようとすると、エディタが即座に怒ってくれる
// userName = 123; // ⚠️ Type ‘number’ is not assignable to type ‘string’.
/
- ユーザーの設定オブジェクト
- @type {{ theme: ‘light’ | ‘dark’, notifications: boolean }}
/
const userSettings = {
theme: “dark”,
notifications: true
};
ここで注目してほしいのは、ユニオン型(`’light’ | ‘dark’`)もJSDocで完全に表現できる点だ。エディタ上で `userSettings.theme = ` と打てば、自動補完で `’light’` と `’dark’` がサジェストされる。これだけでも開発体験(DX)は劇的に跳ね上がる。
—
2. 複雑な構造は `@typedef` と `@property` で型エイリアス化する
実務では、ネストした複雑なJSONデータを扱うことが多いだろう。先ほどのインラインの型定義では、コードがすぐに汚染されてしまう。
そんなときは、TypeScriptの `type` や `interface` に相当する `@typedef` と `@property` を使って、ファイル内(あるいは別ファイルの型定義ファイル)にカスタム型を切り出そう。
/
- @typedef {Object} UserProfile
- @property {number} id – ユーザーを一意に識別するID
- @property {string} name – ユーザーの表示名
- @property {string} [email] – メールアドレス(オプショナルなプロパティ)
- @property {(‘admin’|’user’|’guest’)} role – 権限ロール
/
/
- APIから返却されたユーザーデータを処理する関数
- @param {UserProfile} user – 処理対象のユーザーオブジェクト
- @returns {string} フォーマット済みの紹介文
/
function formatUserProfile(user) {
// ここで user. と打つと、id, name, email, role が完璧に補完される
const emailText = user.email ? `(${user.email})` : ‘(未登録)’;
return `${user.name} [${user.role}] ${emailText}`;
}
// 使用例
const targetUser = {
id: 42,
name: “Takahashi”,
role: “admin”
// emailはオプショナルなので書かなくても怒られない
};
console.log(formatUserProfile(targetUser));
オプショナルなプロパティを表現したいときは、プロパティ名をブラケットで囲む(`[email]`)のがJSDocの作法だ。この「知っているか知らないか」だけで、コードの堅牢性が段違いになる。
—
3. 現場で役立つ!JSDoc運用のベストプラクティス
さて、ここまで基礎を話したが、実務でJSDocを導入するにあたって、シニアとしていくつか現場の知見を共有しておこう。
① 型定義ファイルを別出しする(`.d.js` や `types.js`)
全てのJSファイルの頭に長大な `@typedef` を書いていると、肝心のビジネスロジックが見づらくなる。
プロジェクトのルートに `types.js`(またはVSCodeなら `jsconfig.json`)を置き、そこに型を集約するか、あるいはTypeScriptの `.d.ts` ファイルをそのままJSプロジェクトに読ませることも可能だ。実は、JSDoc環境下でも `.d.ts` は有効に機能する。型が多くなってきたら、型定義は別ファイルに逃がすのがクリーンアーキテクチャの鉄則だ。
② `@ts-check` をファイルの先頭に書く
JSDocによる型チェックをそのファイルで厳格に有効化するには、ファイルの最上部に以下の一行を記述する。
// @ts-check
これがないと、エディタによってはJSDocの記述ミス(存在しない型名を書くなど)をスルーしてしまう。チームで開発する際は、ESLintの設定と組み合わせて、全ファイルの先頭に `@ts-check` を強制する、あるいはプロジェクト全体の `jsconfig.json` で有効化するのがベストだ。
{
“compilerOptions”: {
“checkJs”: true,
“target”: “esnext”,
“module”: “commonjs”
}
}
この `jsconfig.json` を1枚置くだけで、プロジェクト全体が静カスケードの恩恵を受ける要塞に変貌する。
—
おわりに
JSDocは、決して「TypeScriptが使えない現場の妥協案」などではない。
「ビルドの複雑さを持ち込みたくないが、エディタの強力な支援と型安全性は妥協したくない」という、シビアなフロントエンドエンジニアの要求に応えてくれる、極めて洗練された現実解だ。
まずは身近なユーティリティ関数や、散らかりがちな設定オブジェクトのファイルから、`// @ts-check` と `@type` を仕込んでみてほしい。エディタが赤波線でバグを事前に教えてくれるあの安心感を味わったら、もう裸のJavaScriptには戻れなくなるはずだ。
さあ、今日から君のコードベースを少しずつ硬く、美しくしていこうか。

コメント