🫥

インデックスアクセス時にundefinedを考慮する

2024/12/17に公開

JavaScriptの特徴的な挙動の一つとして、配列やオブジェクトに存在しないインデックスやプロパティにアクセスするとundefinedが返される点があります。
この挙動は実行時エラーを引き起こす原因となるため注意が必要です。(自戒を込めて)
その問題を防ぐため、TypeScriptでは明示的にundefinedを考慮した安全なコードを書くことが推奨されます。

また、オブジェクトのプロパティアクセスでも同様の問題が発生する可能性があります。存在しないプロパティにアクセスした場合、その結果もundefinedとなります。


存在しないインデックスやプロパティにアクセスすると

以下の例では、存在しない配列のインデックスやオブジェクトのプロパティにアクセスした結果、エラーが発生します。

配列の場合

const arr: string[] = [];
const value = arr[0]; // value は undefined

const upperValue = value.toUpperCase(); // 実行時エラー: Cannot read properties of undefined
console.log(upperValue);

オブジェクトの場合

const obj: { [key: string]: string } = {};
const value = obj["nonExistentKey"]; // value は undefined

const upperValue = value.toUpperCase(); // 実行時エラー: Cannot read properties of undefined
console.log(upperValue);

解決策

1. noUncheckedIndexedAccessオプションの有効化

tsconfig.jsonにて、noUncheckedIndexedAccessを有効にすることで、インデックスやキーでのアクセス時にundefinedを考慮した型を自動的に適用できます。

{
  "compilerOptions": {
    "noUncheckedIndexedAccess": true
  }
}

このオプションを有効にすると、以下のように型が強化されます。

  • 配列のインデックスアクセス: T | undefined
  • オブジェクトのプロパティアクセス: T | undefined

これにより、undefinedを考慮しないコードはコンパイル時にエラーとして検出されます。


2. 安全なアクセス方法

以下はnoUncheckedIndexedAccess有効時の安全なコード例です。

配列の場合
const arr: string[] = [];
const value = arr[0]; // 型は string | undefined

// オプショナルチェーンを使った安全なアクセス
const upperValue = value?.toUpperCase();
console.log(upperValue); // undefined
オブジェクトの場合
const obj: { [key: string]: string } = {};
const value = obj["nonExistentKey"]; // 型は string | undefined

// オプショナルチェーンを使った安全なアクセス
const upperValue = value?.toUpperCase();
console.log(upperValue); // undefined

3. undefinedの特定処理

undefinedのケースを明示的に処理したい場合、if文やデフォルト値を活用できます。

if文での処理
if (value === undefined) {
  console.log("値が存在しません");
} else {
  console.log(value.toUpperCase());
}
デフォルト値の設定
const upperValue = (value ?? "default").toUpperCase();
console.log(upperValue); // default

まとめ

TypeScriptのnoUncheckedIndexedAccessオプションを有効にすると、潜在的なエラーを未然に防ぐことができます。また、undefinedを安全に処理するための機能(オプショナルチェーンや??)を活用することで、実行時エラーを回避し、信頼性の高いコードを書くことが可能です。
途中から導入すると大変な時もある😺かも

Discussion