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`の扱いには迷わないはずだ。現場のコードで「数値の型」に敏感になること。それが、信頼されるエンジニアへの第一歩だ。

コメント