switchで一部returnを書き忘れた原因と直し方
union型の値をswitch文で分岐する関数で、一部のケースにしかreturnを書かないと、「関数がreturn文で終わっていない」というエラーになります。TypeScriptはunion型の全パターンをたどって、返し忘れがないかを検査します。
エラーメッセージの読み方
main.ts(2,26): error TS2366: Function lacks ending return statement and return type does not include 'undefined'.
main.ts- ファイル名
2- 行番号
26- 列番号 — この位置でtscが検査に失敗しました
TS2366- エラーコード — 検索するとTypeScriptの解説が見つかります
Function lacks ending return statement and return type does not include 'undefined'.- 内容 — 期待していたもの、または受け付けられなかったもの
このエラーが出る典型パターン
パターン1
1 type Shape = { kind: "circle"; radius: number } | { kind: "square"; side: number }; 2 function area(s: Shape): number { 3 switch (s.kind) { 4 case "circle": 5 return Math.PI * s.radius * s.radius; 6 ^ 7 } 8 } 9 console.log(area({ kind: "square", side: 4 }));
squareのケースにreturnが無いため、switch文が値を返さずに終わる経路が生まれます。全パターンをカバーしていないとtscが検出します。
直し方: (空) を case "square":
return s.side * s.side; にします。
パターン2
1 type Payment = { kind: "card" } | { kind: "cash" }; 2 function fee(p: Payment): number { 3 switch (p.kind) { 4 case "card": 5 return 3; 6 ^ 7 } 8 } 9 console.log(fee({ kind: "cash" }));
cashのケースを網羅していないため、switch文を抜けてもreturnされない経路があります。
直し方: (空) を case "cash":
return 0; にします。
パターン3
1 type Level = { kind: "low" } | { kind: "high" }; 2 function score(l: Level): number { 3 switch (l.kind) { 4 case "low": 5 return 1; 6 ^ 7 } 8 } 9 console.log(score({ kind: "high" }));
highのケースを書き忘れると、その経路でreturnされずに関数が終わってしまいます。
直し方: (空) を case "high":
return 10; にします。
パターン4
1 type Light = { kind: "red" } | { kind: "green" }; 2 function action(l: Light): string { 3 switch (l.kind) { 4 case "red": 5 return "stop"; 6 ^ 7 } 8 } 9 console.log(action({ kind: "green" }));
greenのケースにreturnが無いため、switch文が値を返さずに終わる経路が生まれます。
直し方: (空) を case "green":
return "go"; にします。
パターン5
1 type Media = { kind: "audio" } | { kind: "video" }; 2 function play(m: Media): string { 3 switch (m.kind) { 4 case "audio": 5 return "sound"; 6 ^ 7 } 8 } 9 console.log(play({ kind: "video" }));
videoのケースを網羅していないため、switch文を抜けてもreturnされない経路があります。
直し方: (空) を case "video":
return "stream"; にします。
よくある誤解
「該当しないケースは実行時に来ないはずだから、書かなくても大丈夫」という判断は、tscの型チェックには通用しません。実行時の可能性ではなく、型として定義された全パターンを静的に検査します。
実務での勘所
このエラーは、union型に特化した特別な検査ではなく、C#やJavaにもある「全ての経路が値を返しているか」という一般的な制御フロー解析の一例です。switchの一部のcaseだけにreturnがあると、該当しなかった残りのcaseがreturn文を経由せずに関数の末尾へ抜けてしまいます。union型の全パターンを網羅していないこと自体は間接的な結果であって、直接検出されているのは「returnせずに関数の外に出る経路が存在する」という、より一般的な制御フローの問題です。