文字列リテラルをenum型の引数に渡すとエラーになる理由
enumで定義した型は、見た目が近い文字列リテラルであっても別の型として扱われます。enumのメンバー名と同じ文字列を渡しても、enum型そのものの値でなければ代入・引数として受け付けられません。
エラーメッセージの読み方
main.ts(8,20): error TS2345: Argument of type '"Active"' is not assignable to parameter of type 'Status'.
main.ts- ファイル名
8- 行番号
20- 列番号 — この位置でtscが検査に失敗しました
TS2345- エラーコード — 検索するとTypeScriptの解説が見つかります
Argument of type '"Active"' is not assignable to parameter of type 'Status'.- 内容 — 期待していたもの、または受け付けられなかったもの
このエラーが出る典型パターン
パターン1
1 enum Status { 2 Active, 3 Inactive, 4 } 5 function report(s: Status): string { 6 return `status=${s}`; 7 } 8 console.log(report("Active" )); ^
"Active"はただの文字列であり、enumのStatus.Activeとは別の型です。メンバー名と同じ文字列を渡しても通用しません。
直し方: "Active" を Status.Active にします。
パターン2
1 enum Color { 2 Red, 3 Blue, 4 } 5 function paint(c: Color): string { 6 return `color=${c}`; 7 } 8 console.log(paint("Red" )); ^
文字列の"Red"とColor.Redは別の型です。enumのメンバーそのものを渡す必要があります。
直し方: "Red" を Color.Red にします。
パターン3
1 enum Level { 2 Low, 3 High, 4 } 5 function setLevel(l: Level): string { 6 return `level=${l}`; 7 } 8 console.log(setLevel("Low" )); ^
Level.Lowと文字列"Low"は別の型として扱われます。setLevelにはenumの値そのものを渡す必要があります。
直し方: "Low" を Level.Low にします。
パターン4
1 enum Mode { 2 Auto, 3 Manual, 4 } 5 function setMode(m: Mode): string { 6 return `mode=${m}`; 7 } 8 console.log(setMode("Auto" )); ^
"Auto"はただの文字列であり、enumのMode.Autoとは別の型です。
直し方: "Auto" を Mode.Auto にします。
パターン5
1 enum Size { 2 Small, 3 Large, 4 } 5 function pick(s: Size): string { 6 return `size=${s}`; 7 } 8 console.log(pick("Small" )); ^
文字列の"Small"とSize.Smallは別の型です。enumのメンバーそのものを渡す必要があります。
直し方: "Small" を Size.Small にします。
よくある誤解
「enumのメンバー名と同じ文字列を渡せば通じるはず」という考えは誤りです。TypeScriptのenumは独自の名前的型(nominal-ishな型)を持ち、文字列リテラル型とは構造が似ていても別物として扱われます。
実務での勘所
TypeScriptのコミュニティでは、enumの代わりに文字列リテラルのunion型(type Status = "active" | "inactive";)を使うことを推奨する意見が広がっています。リテラルユニオンは普通の文字列リテラルとして扱えるため、このトピックのような「見た目は同じ文字列なのに型が違う」という混乱が起きません。enumはコンパイル後に実体を持つオブジェクトを生成するなど独自の癖も多く、新しいコードではenumより文字列リテラルのunion型を選ぶスタイルガイドが増えています。