【実務・中級編】 BigIntの型判定とtypeof演算子の挙動 – JavaScript実践ガイド

BigIntの「罠」と型判定のリアル:Numberとの境界線を見極める

フロントエンドの現場でAPIから巨大なID(例えば19桁のTwitter/Xの雪片IDなど)を受け取ったとき、`JSON.parse`した瞬間に末尾の数値が丸められて絶望した経験はないだろうか?

JavaScriptにおける数値の扱いは、長らく`Number`(IEEE 754倍精度浮動小数点数)という「諸刃の剣」に頼らざるを得なかった。しかし、そこに現れたのが`BigInt`だ。今日は、この`BigInt`を扱う際に多くのエンジニアが躓く「型判定の正体」と、実務で事故を起こさないための鉄則を伝授しよう。

—

typeofで返る「bigint」という文字列の重み

結論から言おう。`typeof`演算子において、`BigInt`は明確に独立した型として定義されている。

const smallNumber = 100;
const bigNumber = 100n;

console.log(typeof smallNumber); // “number”
console.log(typeof bigNumber); // “bigint”

この「`bigint`」という文字列が返ることは、ECMAScript仕様上の大きな転換点だった。かつて我々は、巨大な整数を扱うために文字列型で受け取ったり、ライブラリで解決したりしていたが、現在は言語仕様レベルでこの区別が担保されている。

ここで重要なのは、「`Number`と`BigInt`は、厳密な等価演算子(`===`)で比較すると、値が同じでも必ず`false`になる」という点だ。

// ここが現場でバグを生む温床になりやすい
console.log(10n === 10); // false。型が違うので比較すら成立しない

この挙動を理解していないと、「APIから来た数値とフロントで計算した数値を`===`で比較したら、なぜか弾かれる」という、深夜のデバッグを強いる悪夢のようなバグに遭遇することになる。

—

なぜ混ぜるな危険なのか?(ブラウザ内部の事情)

ブラウザのJavaScriptエンジン(V8など)において、`Number`は浮動小数点数として処理され、CPUの浮動小数点演算器(FPU)をフル活用する。一方で`BigInt`は、メモリ上に可変長の整数として確保されるため、演算の仕組みが根本的に異なる。

JavaScriptのエンジンは、この2つを混合した算術演算を「型エラー(TypeError)」として遮断する。これは、意図しない暗黙の型変換による精度欠損(例:`Number`へのキャストによる丸め)を未然に防ぐための、言語設計者からの強力なガードレールだ。

—

実践的:事故を防ぐための「型判定ユーティリティ」

実務において、「これは`Number`なのか`BigInt`なのか」を判定して処理を分岐させるケースは頻出する。以下のようなユーティリティを用意しておくのが、中級者から一歩先へ進むためのベストプラクティスだ。

/

  • 安全に数値を判定し、処理を分岐させるためのガード関数

/
function handleNumericalValue(value) {
if (typeof value === ‘bigint’) {
// BigInt型だった場合の処理(例:精度を落とさずに通信したい場合など)
return value.toString();
}

if (typeof value === ‘number’ && Number.isFinite(value)) {
// 通常のNumber型だった場合の処理
return value.toFixed(2);
}

throw new Error(‘未対応の数値型です’);
}

// 使用例
console.log(handleNumericalValue(12345678901234567890n)); // “12345678901234567890”
console.log(handleNumericalValue(42.195)); // “42.20”

—

シニアからのアドバイス:現場での「暗黙の型変換」は禁忌

よく「`Number(myBigInt)`とすればいいのでは?」という声を聞くが、これは禁じ手だ。`BigInt`を`Number`に強制変換すると、大きな値の場合は精度が失われ、情報が欠損する。

もしプロジェクトで「JSONを扱う」のであれば、`JSON.stringify`に`BigInt`を渡すと`TypeError`で落ちることも覚えておいてほしい。`BigInt`をJSONとして送信したい場合は、オブジェクトのシリアライズ時に`toJSON`メソッドをオーバーライドするか、通信の直前で文字列化するフローをアーキテクチャに組み込む必要がある。

まとめ:

  • `typeof`で`bigint`が返ることを信頼せよ。
  • `Number`と`BigInt`を`===`で比較してはならない。
  • 暗黙の型変換に頼らず、必ず明示的な変換(`toString`や`BigInt()`)を通すこと。

JavaScriptは柔軟だが、その柔軟さが仇になることもある。特に数値の精度問題は、一度バグると検知が難しい。この記事を読んだ君なら、もう`10n`の扱いには迷わないはずだ。現場のコードで「数値の型」に敏感になること。それが、信頼されるエンジニアへの第一歩だ。

コメント

タイトルとURLをコピーしました