TypeScript「Object is possibly 'undefined'」エラーの修正方法 (ts2532)

beginner🔵 TypeScript2026-03-20| TypeScript 4.x / 5.x、Node.js、React、あらゆるTypeScriptプロジェクト

Error Message

Object is possibly 'undefined'. ts(2532)
#typescript#undefined#nullチェック#オプショナルチェーン

エラーの内容

Object is possibly 'undefined'. ts(2532)

TypeScript が undefined になる可能性のある値を検出しました。チェックなしでその値を使おうとしています。コンパイラは意図的にこれをブロックします。実行時にその値が本当に undefined だった場合、アプリがクラッシュします。

よくあるトリガー:

  • インデックスによる配列要素へのアクセス:arr[0].name
  • Map の検索結果の読み取り:map.get(key).value
  • チェックなしで使用されるオプションの関数パラメータ
  • DOM クエリ:document.querySelector('#btn').addEventListener(...)
  • T | undefined として型付けされたプロパティ

根本原因

厳格な null チェック(strictNullChecks: true)は、tsconfig.json"strict": true を使用するとデフォルトで有効になります。このフラグが有効な場合、undefined は独自の型になります。TypeScript は T | undefined の値を常に T であるかのように扱うことを許可しません。

最小限の再現例:

const users: User[] = getUsers();
const first = users[0]; // 型: User | undefined
console.log(first.name); // ❌ Object is possibly 'undefined'. ts(2532)

配列インデックスアクセスが T | undefined を返すのは、インデックス 0 が存在しない可能性があるためです。たとえば、getUsers() が空の配列を返す場合などです。

修正方法 — 複数のアプローチ

1. オプショナルチェーン(?.)— 読み取りに最もシンプル

?. 演算子は短絡評価を行い、スローする代わりに undefined を返します。余分な変数は不要です。

console.log(first?.name); // ✅ first が undefined なら undefined を返す

// 必要なだけ深くチェーンできる
console.log(user?.address?.city);

// メソッド呼び出しにも使える
user?.save();

undefined の結果が許容される場合(値が欠けていると何も表示しない UI のレンダリングなど)は、まずこれを検討してください。

2. Null 合体演算子(??)— フォールバックを提供する

値が欠けている場合のデフォルトを提供するために、?? とオプショナルチェーンを組み合わせます:

const name = user?.name ?? 'Anonymous';
const count = map.get(key)?.total ?? 0;

3. 明示的な if チェック(型ガード)

値に対して複数行のロジックを実行する必要がある場合、ガードブロックの方が ?. をあちこちに散りばめるより整理されます。

const first = users[0];
if (first) {
  console.log(first.name); // ✅ TypeScript はここで User に絞り込む
  first.activate();
  first.trackVisit();
}

// 関数では早期リターンが効果的
function greet(user: User | undefined) {
  if (!user) return;
  console.log(`Hello, ${user.name}`); // ✅ 安全
}

4. 非 null アサーション(!)— 慎重に使用する

! 演算子はコンパイラへの約束です:「この値は undefined ではない — 保証する」。TypeScript はそれを信頼してチェックをスキップします。実行時の安全性はゼロです。

const btn = document.querySelector('#submit')!;
btn.addEventListener('click', handleClick); // ✅ コンパイラは満足

// インラインバージョン
console.log(users[0]!.name);

これは本当に確実な状況(React コンポーネントの useEffect でレンダリングした直後の DOM 要素など)に限定してください。! を至る所に使うと、厳格な null チェックの意味が完全に失われます。

5. 配列インデックスアクセス — noUncheckedIndexedAccess を有効にする

このエラーが特に arr[i] で発生していますか?TypeScript 4.1 では、プロジェクト全体でこれを明示的にする noUncheckedIndexedAccess が追加されました:

// tsconfig.json
{
  "compilerOptions": {
    "noUncheckedIndexedAccess": true
  }
}

これを有効にすると、arr[0] はどこでも T | undefined として型付けされます — 予期しない動作はありません。使用前にガードしてください:

const first = users[0];
if (first !== undefined) {
  console.log(first.name); // ✅
}

6. Map.get() パターン

const cache = new Map();

// 修正前
const config = cache.get('main');
config.timeout = 5000; // ❌ possibly undefined

// 修正後 — ガード
const config = cache.get('main');
if (config) {
  config.timeout = 5000; // ✅
}

// 修正後 — フォールバック
const config = cache.get('main') ?? defaultConfig;
config.timeout = 5000; // ✅

7. DOM クエリ

querySelectorundefined ではなく Element | null を返しますが、同じ修正が適用されます:

const btn = document.querySelector('#submit');

// オプション A: 非 null アサーション(要素の存在が確実な場合のみ)
btn!.addEventListener('click', handleClick);

// オプション B: ガード(DOM に存在しない可能性がある要素には安全)
if (btn) {
  btn.addEventListener('click', handleClick);
}

非 null アサーションを使ってはいけない場合

実行時に本当にオプショナルな値があります。それらに ! を使うと、コンパイル時エラーが実行時クラッシュに変わり、より悪い結果になります。

  • API レスポンス:古いサーバーバージョンやエラー状態ではフィールドが欠けている場合がある
  • ユーザー入力とフォームの値
  • ファイルや環境変数から読み込まれた設定
  • 厳格な型付けのないサードパーティライブラリからのデータ

これらすべてに対して、実際のガードを記述するかフォールバックを提供してください。

確認方法

TypeScript コンパイラを直接実行して、エラーが残っていないことを確認します:

# プロジェクト全体をチェック
npx tsc --noEmit

# 単一ファイルをチェック
npx tsc --noEmit src/utils.ts

VS Code では、保存するとすぐに赤い波線が消えます。変数にホバーしてください — TypeScript が User | undefined から User に絞り込んでいれば、修正が機能しています。

予防策

  • tsconfig.json"strict": true を維持してください。このエラーを黙らせるために strictNullChecks を無効にするのは修正ではありません
  • 外部データソースからネストされたプロパティを読み取る際は、デフォルトで ?. を使用してください
  • DOM クエリには型付きジェネリクスを使用してください:querySelector<HTMLInputElement>
  • 関数に明示的な戻り値の型を追加してください — 何かが undefined を返す可能性があることが明確になります
  • Zod のようなスキーマライブラリでエントリポイントで API レスポンスを検証し、内部型が常に完全に定義されるようにしてください

Related Error Notes