Loading

ROUTE

ルートゼロの
アクティビティ

JavaScript Optional Chainingの使い方|?.を使う場所・使わない場所

2

`Cannot read properties of undefined` を止めるために、見つけたプロパティへ片っ端から `?.` を付けていないでしょうか。Optional Chaining(オプショナルチェーン)は、`null` や `undefined`
の可能性がある値へ安全にアクセスするための便利な構文です。ただし、エラーを出さなくすることと、コードが正しくなることは同じではありません。この記事では `?.`
の書き方だけでなく、「欠損を許容してよい場所か」を基準に、使う場所・使わない場所をコードで整理します。

結論:「欠損を許容してよい場所」で使う

Optional Chainingを使うか迷ったら、最初に確認したいのは「その値が無くても正常な状態と言えるか」です。ユーザーの任意プロフィール、存在しないことが仕様上あり得るAPI項目、任意コールバックなどは `?.`
と相性が良い対象です。

状況 おすすめ 理由
途中の値が無いことを仕様として許容する `?.` を使う `null` / `undefined` で安全に短絡し、`undefined` を返せる
本来必須のオブジェクトが無い 入力・状態を検証する `?.` で握りつぶすと、本来の不具合に気付きにくい
無い場合の表示値・既定値が必要 `?.` と `??` を組み合わせる 欠損時の挙動を明示できる
変数自体が宣言されていない 宣言・スコープを直す `undeclaredVar?.prop` でもReferenceErrorになる

つまり `?.` は「エラーを消す記号」ではなく、「ここは値が無い状態を許容する」という設計意図をコードに表すために使う、と考えると判断しやすくなります。


Optional Chaining(?.)とは

Optional Chaining(`?.`)は、オブジェクトのプロパティ参照や関数呼び出しを行うとき、評価対象が `null` または `undefined` なら、その時点で処理を短絡して `undefined` を返す構文です。ECMAScript
2026仕様でも、Optional Chainの基底値が `undefined` または `null` の場合は `undefined` を返すことが定義されています。

用語解説:nullish
JavaScriptでは、`null` または `undefined` のどちらかである状態をまとめてnullishと呼びます。Optional Chainingが短絡するのは、この2種類です。

const user = {};

// profileがないためTypeError
// console.log(user.profile.name);

const name = user.profile?.name;
console.log(name); // undefined

`user.profile?.name` では、`profile` が `undefined` なので `.name` へ進まず、式全体が `undefined` になります。`false`、`0`、空文字列のような値まで欠損扱いするわけではありません。

(Cannot read properties系のエラーが起きる原因から切り分けたい場合については『TypeError: Cannot read property ‘xxx’ of undefined の原因と対処法を徹底解説【初心者向け】』をご参照ください)


プロパティ・配列・関数での使い方

`?.` は、通常のドット記法だけでなく、配列や動的キーのブラケット記法、任意の関数呼び出しにも使えます。まずは「値が無いことが仕様上あり得る場所」に限定して使うのが安全です。

// 1. プロパティ
const city = user.address?.city;

// 2. 配列・動的キー
const firstItem = response.items?.[0];
const key = "theme";
const theme = settings?.[key];

// 3. 任意のコールバック
onSuccess?.(result);

関数呼び出しでは、対象の関数が存在しなければ `undefined` が返ります。ただし、プロパティ自体は存在するものの値が関数ではない場合、`callback?.()` としても `TypeError`
になります。オブジェクト側も欠損し得るなら `service?.run?.()` のように、それぞれの境界を分けて考えます。


カジュアル面談はこちら

??と組み合わせて既定値を決める

Optional Chainingで得られる値は、途中が欠損していれば `undefined` になります。画面表示などで既定値が必要なら、Nullish Coalescing演算子(`??`)を組み合わせると意図を明確にできます。

const city = user.address?.city ?? "未設定";
const firstName = users?.[0]?.name ?? "該当ユーザーなし";

`??` が右辺へ切り替わるのは `null` または `undefined` のときだけです。`||` は `0`、`false`、空文字列も偽値として右辺へ切り替えるため、0件や空文字列を有効値として残したい場面では挙動が異なります。

使いすぎるとバグを隠す:?.を使わない方がよい場面

一番注意したいのは、本来必須のデータに `?.` を重ねて「エラーだけ消す」使い方です。たとえば注文オブジェクトが必須なのに、`order?.items?.`
と書けば異常な状態でも処理が静かに進みます。結果として、原因の発見が遅れることがあります。

// 悪い例:order自体が必須なのに欠損を許容してしまう
const total = order?.items?.reduce(
  (sum, item) => sum + item.price,
  0
);

// 改善例:必須値は先に検証する
if (!order) {
  throw new Error("order is required");
}

const total = order.items?.reduce(
  (sum, item) => sum + item.price,
  0
) ?? 0;
  • API契約で必須とされているレスポンス項目
  • アプリ起動に必要な設定オブジェクト
  • 状態管理上、存在しないと設計違反になる値
  • 必須フォーム値や必須ルートパラメータ

こうした値は、使用地点で `?.` を追加するより、データを受け取る境界で検証する方が原因を追いやすくなります。Optional
Chainingは「欠損してよい値」のために残しておくと、コードから設計意図も読み取りやすくなります。

(そもそもundefinedがどこで生まれているかをデバッグしたい場合については『なぜ「undefined」が出る?原因と解決法10選|JavaScript のデバッグに効く実例集』をご参照ください)

?.でも防げないケース

`?.` を付ければ、どんなTypeErrorやReferenceErrorも防げるわけではありません。特に次の4つは、実務で「?.を付けたのに落ちる」原因になりやすいポイントです。

ケース コード例 結果
未宣言の変数 `undeclaredVar?.prop` ReferenceError。Optional Chainingは未宣言ルートを作らない
存在するが関数ではない `obj.method?.()` `method`が非関数ならTypeError
チェーン途中をグルーピング `(user?.profile).name` `user`がnullishなら、その後の`.name`でTypeErrorになり得る
代入先として使う `obj?.prop = 1` SyntaxError。Optional Chainの評価結果には代入できない
const user = null;

// 連続したチェーンなら短絡する
const safeName = user?.profile?.name;

// グルーピングすると、その後の .name は別評価になる
// const unsafeName = (user?.profile).name; // TypeError

MDNでは、`new Intl?.DateTimeFormat()` のように `new` のコンストラクター部分へOptional Chainingを使う構文や、タグ付きテンプレートへ使う構文も無効とされています。`?.`
は「プロパティ参照・ブラケットアクセス・関数呼び出しなら何でも置ける記号」ではない点に注意してください。

実務で迷わない判断フロー

コードレビューで `?.` の妥当性を判断するときは、構文から見るより、値の契約から逆算すると迷いにくくなります。

  • 1. その値は無くても正常か。YESなら `?.` の候補にする
  • 2. 無いこと自体が異常か。YESなら、`?.` ではなく入力・状態を先に検証する
  • 3. 欠損時に表示値や既定値が必要か。必要なら `?.` の後ろへ `??` を付ける
  • 4. `?.` を追加してエラーが消えた後、なぜnullishになったかを説明できるか確認する
  • 5. チェーンが長い場合は、どの段階まで欠損を許容する仕様なのかを明確にする

たとえば `user?.company?.address?.city` が動くことと、`user`・`company`・`address` のすべてが任意でよいことは別問題です。仕様上任意なのが `address` だけなら、上流で `user` と `company`
を保証したうえで `user.company.address?.city` とした方が、異常と許容可能な欠損を区別できます。

まとめ:?.はエラーを消す道具ではなく「欠損を許容する」宣言

  • Optional Chainingは、対象が`null`または`undefined`なら短絡して`undefined`を返す
  • `obj?.prop`、`obj?.[expr]`、`func?.()`の3パターンを基本として覚える
  • 欠損時の既定値が必要なら`??`と組み合わせる
  • 必須データに`?.`を重ねると、エラーは消えても不具合の原因を隠す可能性がある
  • 未宣言変数、非関数呼び出し、グルーピング、無効な代入などは`?.`でも解決しない

`Cannot read properties of undefined` に遭遇したら、まず「このプロパティは本当に任意なのか」を確認してください。任意なら `?.`、必須なら上流のデータや状態を直す。この分け方を先に決めると、Optional
Chainingを便利に使いながら、エラーの原因まで隠してしまうコードを減らせます。

RANKINGranking-icon

すべてを開示している会社です

ポジティブな面もネガティブな面も、包み隠さず誠実にお答えします。
気になることがあれば、面談の際にすべてオープンにお話します。