こんにちは!フロントエンドの現場を渡り歩いてきたチーフアーキテクトの私です。
JavaScriptを書いていると、ふとこんな不安に襲われたことはありませんか?
「あれ、この関数に渡すステータスって、’success’だっけ? ‘SUCCEEDED’だっけ? それともただの1?」
「うっかりスペルミスして、誰も気づかないままバグが本番にデプロイされちゃった……!」
JavaScriptには、TypeScriptのようなガチガチの「列挙型(enum)」が標準ではありません。だからこそ、現場ではみんな「文字列のベタ書き(マジックストリング)」でなんとか乗り切ってきた歴史があります。でも、それってもはや「お祈りプログラミング」ですよね。
「型安全が欲しいけど、いきなりTypeScriptを導入するのはハードルが高い……」
そんなあなたにこそ知ってほしいのが、JSDocの`@enum`を使った定数セットの型定義です!
今回は、JavaScriptのままで、うっかりミスをビシッと防ぐ「ちょっとズルくて最高に実用的なテクニック」を、一緒に優しく紐解いていきましょう。大丈夫、決して難しくありませんよ。
—
そもそも「@enum」ってなに? 身近な例えで考えてみよう
いきなりコードを見る前に、イメージを掴みましょう。
例えば、あなたが近所のカフェでアルバイトを始めたとします。メニューには「ホットコーヒー」「アイスティー」「カフェラテ」しかありません。
もし、お客さんが「どら焼きください!」と言ってきたらどうしますか? 「当店にはございません」とお断りしますよね。
プログラムもこれと同じです。
関数が受け取れる値の「メニュー(選択肢)」をあらかじめ限定しておけば、お客さん(他のコードや自分自身)が変な注文をしてきたときに、事前に「そんなメニューないよ!」と気づくことができます。
この「決められた選択肢のセット」を作るのが、JSDocの`@enum`です。
—
さっそく書いてみよう! 基本の形
JavaScriptのエディタ(VS Codeなど)を開いて、こんな風に書いたことはありませんか?
// よくある普通のオブジェクト
const Role = {
ADMIN: ‘admin’,
USER: ‘user’,
GUEST: ‘guest’
};
これだけでも「`Role.ADMIN`と書けばスペルミスしにくいな」というメリットはありますが、VS Codeは「この変数には、この中のどれかしか入れちゃダメだよ!」とは教えてくれません。
ここに、魔法のひと言(JSDocコメント)を添えてあげます。
/
- ユーザーの権限を表す列挙型
- @readonly
- @enum {string}
/
const Role = {
ADMIN: ‘admin’,
USER: ‘user’,
GUEST: ‘guest’
};
たったこれだけ!これだけで、VS Codeの世界が変わります。
`@readonly`は「あとから値を変えちゃダメだよ」というお約束、`@enum {string}`は「この中身はすべて文字列のグループだよ」という宣言です。
—
現場でどう役立つの? エディタの補完と恩恵
例えば、ユーザーの権限を受け取って処理を分岐させるこんな関数を作ったとします。
/
- 権限に応じたメッセージを表示する関数
- @param {Role[keyof Role]} userRole – Roleオブジェクトのいずれかの値
/
const showWelcomeMessage = (userRole) => {
if (userRole === Role.ADMIN) {
console.log(‘ようこそ、管理者さま!’);
} else {
console.log(‘いらっしゃいませ!’);
}
};
ちょっと見慣れない `@param {Role[keyof Role]}` という呪文が出てきましたが、要するに「Roleのどれかの値(’admin’, ‘user’, ‘guset’のいずれか)だけを受け付けます」という意味です。
これを書くと何が嬉しいかというと、関数に値を渡そうとしたときに、VS Codeが「おいおい、ここに使えるのはこれらの中身だけだぜ」と、自動補完(インテリセンス)でリストを表示してくれるんです。
さらに、うっかり `showWelcomeMessage(‘admiin’)` のようにタイポ(入力ミス)した瞬間、エディタが波線で「おいおい、そんな値は許可されてないよ」と優しく(時に厳しく)教えてくれます。本番環境に行く前にバグの芽を摘める、これが最大の醍醐味です。
—
数値のパターンでも使えるの?
もちろん、文字列だけでなく数値でも使えます。例えば、お買い物のステータス管理(0: 未払い、1: 支払済み、2: 発送済み)などで大活躍します。
/
- 注文ステータス
- @readonly
- @enum {number}
/
const OrderStatus = {
UNPAID: 0,
PAID: 1,
SHIPPED: 2
};
/
- ステータスに応じた処理
- @param {OrderStatus[keyof OrderStatus]} status
/
const updateShipping = (status) => {
if (status === OrderStatus.PAID) {
console.log(‘商品の梱包を開始します!’);
}
};
// 正しい使い方
updateShipping(OrderStatus.PAID);
// ❌ 間違った値(3など)を入れようとすると、エディタが警告を出してくれます
updateShipping(99);
「数字の意味(マジックナンバー)をそのままコードに書くのはやめようね、定数に名前をつけようね」というシニアエンジニアたちの教えを、JSDocが強力にバックアップしてくれるわけです。
—
まとめ:今日から「お祈りコード」を卒業しよう
いかがでしたでしょうか?
「JavaScriptは型がないからカオスになって当たり前」なんて思っていませんでしたか?
TypeScriptを導入するほどのプロジェクト規模ではない、あるいは、素のJavaScript(Vanilla JS)の身軽さを愛しているという現場でも、JSDocの`@enum`を使えば、今日のその日からエディタの賢い補完と型チェックの恩恵を受けることができます。
「スペルミスで3時間溶かした……」なんて悲しい残業とは、今日でおさらばしましょう。
まずは身近な定数ファイルを一つ選んで、頭に `/ @enum {string} /` をぽんと添えてみてください。エディタがフワッと優しくあなたをサポートしてくれる心地よさに、きっと病みつきになりますよ!
それでは、快適なJavaScriptライフを!チーフアーキテクトの私でした。

コメント