Code Fix

初級

配列の範囲外アクセスがエラーにならずundefinedになる(TypeScriptでも変わらない)

TypeScriptは配列の要素数を型では追跡しないため、number[]のような型でも範囲外アクセスはコンパイルエラーになりません。実行時もJavaScriptと同じく、静かにundefinedを返します。

なぜエラーが出ないのか

出力: undefined
(エラーなし)
TypeScriptは何も報告しません。型検査も構文も正しいためです
出力: undefined
実際の挙動 — 期待した結果と食い違っている箇所
見つけ方
エラーが出ないので、出力を目で確かめるか、コードを目で追うしかありません。この種の誤りが最も発見が遅れます

このエラーが出る典型パターン

パターン1

 1  const nums: number[] = [10, 20, 30];
 2  console.log(nums[5]);
                     ^
出力: undefined

nums[5]は範囲外です。TypeScriptもJavaScriptと同じくエラーにはならず、静かにundefinedを返します。

直し方: 5 を 1 にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  const colors: string[] = ["red", "green", "blue"];
 2  console.log(colors[10]);
                        ^
出力: undefined

配列の長さは3なのでインデックス10は存在しません。例外にはならず、undefinedが出力されます。

直し方: 10 を 2 にします。

この問題を解いてみる →

パターン3

 1  const scores: number[] = [80, 90];
 2  console.log(scores[-1]);
                        ^
出力: undefined

TypeScriptの配列は負のインデックスを末尾からの参照として扱いません。範囲外と同じくundefinedになります。

直し方: -1 を 0 にします。

この問題を解いてみる →

パターン4

 1  const vals: number[] = [7, 8, 9];
 2  console.log(vals[9]);
                     ^
出力: undefined

vals[9]は範囲外です。例外にはならず、静かにundefinedを返します。

直し方: 9 を 1 にします。

この問題を解いてみる →

パターン5

 1  const words: string[] = ["a", "b"];
 2  console.log(words[-3]);
                       ^
出力: undefined

負のインデックスは末尾からの参照にはならず、範囲外と同じくundefinedになります。

直し方: -3 を 0 にします。

この問題を解いてみる →

よくある誤解

「型を付けたのだから範囲外アクセスも検出してくれるはず」という期待は誤りです。TypeScriptの配列型は要素の型だけを表し、長さや添字の妥当性までは追跡しません。

実務での勘所

この問題に対処するtsconfig.jsonの設定として、noUncheckedIndexedAccessというオプションがあります(strict: trueに自動では含まれない、追加で有効にする必要がある設定です)。これを有効にすると、number[]型の配列に対するarr[i]の型がnumberではなくnumber | undefinedになり、範囲外だった場合の可能性を型として強制的に意識させられます。既定のstrictモードだけでは防げないこの種のバグに対しては、この設定を追加で有効にすることが推奨されています。

演習をはじめる

関連するエラー

他の言語ではどうなるか

広告
広告スロット(未設定)