0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

??を||で書いてしまうと、0や空文字のデフォルト値処理が壊れる理由

0
Posted at

「値が入っていなければデフォルト値を使う」という処理を、次のように||で書いてしまうことがあります。

function getCount(input: { count?: number }) {
  return input.count || 10;
}

console.log(getCount({ count: 0 }));  // 期待: 0 / 実際: 10
console.log(getCount({}));            // 期待: 10 / 実際: 10

countを指定していないときは期待通り10が返りますが、count: 0を明示的に渡したときも10になってしまいます。0という正当な値が入っているのに、デフォルト値に上書きされてしまうのです。

原因: ||は「falsyかどうか」でしか判定しない

||は「左の値がfalsy(偽として扱われる値)なら右を使う」という演算子です。JavaScriptのfalsyには次の6つがあります。

false, 0, '', null, undefined, NaN

||にとっては、「値が入っていない(null/undefined)」も「値は入っているが0''」も、区別なく同じ「falsy」として扱われます。だからcount: 0のような「値としては存在するが、たまたまfalsyな値」まで、まとめてデフォルト値に置き換わってしまいます。

対処: ??(nullish coalescing)を使う

function getCount(input: { count?: number }) {
  return input.count ?? 10;
}

console.log(getCount({ count: 0 }));  // 0(正しく0のまま)
console.log(getCount({}));            // 10

??は「左の値がnullまたはundefinedのときだけ右を使う」という演算子です。判定基準が「falsyかどうか」ではなく「nullundefinedかどうか」というピンポイントなものに変わるため、0''falseのような「値としては存在するfalsy値」はそのまま活かされます。

同じことは文字列でも起きます。

function getName(input: { name?: string }) {
  return input.name || "名無し";
}

function getNameSafe(input: { name?: string }) {
  return input.name ?? "名無し";
}

console.log(getName({ name: "" }));      // 名無し(空文字が上書きされる)
console.log(getNameSafe({ name: "" }));  // ""(空文字のまま)

在庫数の0、入力欄の空文字''、チェックボックスのfalseなど、「意図的にその値にした」ケースを扱うときは??が必須と考えてよいと思います。

?.(optional chaining)と組み合わせるのが定番パターン

プロパティ自体が存在しないかもしれない場合は、?.と組み合わせます。

function getCount(input?: { count?: number }) {
  return input?.count ?? 10;
}

console.log(getCount(undefined)); // 10(inputが無くてもエラーにならない)
console.log(getCount({}));        // 10
console.log(getCount({ count: 0 })); // 0

input?.countは、inputnull/undefinedならその場でundefinedを返し(エラーにならず途中で処理を止める)、inputが存在すれば.countを読みに行きます。その結果を?? 10で受けることで、「inputが無い」「countが無い」「count0」のすべてのケースを、意図通りに処理できます。

注意: ??||&&を括弧なしで混在させるとエラーになる

const a = 1 || 2 ?? 3;

これは動きません。??は優先順位が曖昧になることを避けるため、||&&と同じ式の中で括弧なしに混ぜるとSyntaxErrorになる仕様です。

SyntaxError: Nullish coalescing operator(??) requires parens when mixing with logical operators

||??を同じ式で両方使いたい場合は、(1 || 2) ?? 3のように括弧で優先順位を明示する必要があります。実行時のバグではなくコードを書いた時点でエラーになってくれるので、この組み合わせに気づかず本番に出てしまう心配は少ないですが、初めて見るとエラーメッセージの意味が分かりにくいので覚えておくと安心です。

まとめ

  • ||は「falsyかどうか」で判定するため、0''falseのような正当な値までデフォルト値に置き換えてしまうことがある
  • ??は「nullundefinedかどうか」だけで判定するため、falsyだが意図した値はそのまま活きる
  • input?.count ?? 10のように?.と組み合わせるのが定番
  • ??||&&と括弧なしで混在させるとSyntaxErrorになる(実行前に気づける)

未経験者向けの講座を運営しています

未経験から Next.js + Supabase + Claude Code で Webアプリを公開するまで を、全24セッションで体系化した教材です。Claude Code を学習パートナーにする CLAUDE.md と学習モード(learner / developer)の設計までセットで含みます。

※ 中上級者には易しすぎる内容なので、初心者の知り合いへの紹介や社内研修の参考としてどうぞ。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?