Anker PowerLine III Flow USB-C & USB-C ケーブル Anker絡まないケーブル 100W 結束バンド付き USB PD対応 シリコン素材採用 iPhone 16 / 15 / Galaxy iPad Pro MacBook Pro/Air 各種対応 (1.8m ミッドナイトブラック)
¥1,890 (2025年4月25日 13:07 GMT +09:00 時点 - 詳細はこちら価格および発送可能時期は表示された日付/時刻の時点のものであり、変更される場合があります。本商品の購入においては、購入の時点で当該の Amazon サイトに表示されている価格および発送可能時期の情報が適用されます。)Anker USB Power Strip (10-in-1, 20W) (USBタップ 電源タップ AC差込口/USB-C/USB-A/延長コード 1.5m) 【PSE技術基準適合/USB Power Delivery対応 】MacBook PD対応 Windows PC iPad iPhone Galaxy Android スマートフォン ノートPC 各種 その他機器対応
¥2,990 (2025年4月25日 13:07 GMT +09:00 時点 - 詳細はこちら価格および発送可能時期は表示された日付/時刻の時点のものであり、変更される場合があります。本商品の購入においては、購入の時点で当該の Amazon サイトに表示されている価格および発送可能時期の情報が適用されます。)
どうもこんにちは torihaziです。
今日はTypeScriptのnumberを扱っていた時に
少し詰まったのでその備忘録になります。
特に formで大きな数値を扱ったり、表示したりするときにハマる可能性大です。
今回はreact-hook-formとzodを組み合わせて使用した例を出しています。
例えば 以下のような数値(整数10桁、小数点2桁まで)を入力するformとzodのスキーマがあったとします。
input type=numberを使用しているformです。
ここに例えば 100000000000000000000 (1垓 = 0が20個)を入力します。
その数値までは確かに機能するのでzodのバリデーションも機能するのですが、
そこから0を1個増やすとこの数字は科学的記法に変換されます。
どういうことかというと
1000000000000000000000 (0が21個) => 1e+21
として扱われます。
これが起きるとどうなるかというと、
先ほどのzodのルールをpassします。それもそのはず。
1e+21を toStringした後に “.”でsplitして その後lengthを測るのだから
結果的に 1e+21のlength = 5
これ、useFormのwatchを使って0を書き足して行った時のlogですね。
小数点の方も似たような現象でした。
そこで今回の対応としては次のようにしました。
文字列で受け取るようにして、文字列の正規表現でバリデートする方法です。
これで無事動作しました。
例えば以下のような計算式、出力はどうなると思いますか。
ちなみに数字は100億です。
console.log(10000000000|0)
答えは。
console.log(10000000000|0)
=> 1410065408
なぜでしょうか。
問題の鍵は |(ビット演算子(OR)) にあります。
オペランドは 32 ビットの整数値に変換され、ビット (ゼロまたは 1) の並びによって表現されます。32 ビットを超える数値は最上位のビットが破棄されます。例えば、次の 32 ビットを超える整数は 32 ビット整数に変換されます。
どういうことかというと
1. 10000000000|0 の時点で どちらも32ビットに変換する
2. 10000000000を32ビットに変換
3. しようとしたけど32ビットの最大値を超えてるから切り捨て。
4. 1001010100000010111110010000000000 (34ビット)なので先頭2つを切り捨て
5. 10を切って 01010100000010111110010000000000となる。
6. 残った方を計算すると 1410065408
7. 10000000000|0 => 1410065408 として出力。
ということ。
実際、データベースにはちゃんと100億が記録されていたので
よかったものの少し焦った。
解決策としてはビット演算子を使わなければいいだけのこと。
コード読んでみると “変数 | 0″みたいな書き方をされており、
おそらく undefinedとかだったら 0にするロジックだと判断したので
“変数 ?? 0″として対応したらうまく行った。
昔の誰か(もしかしたら自分が) ||と書き間違えたのかもしれない。
とにかくよかった。
最近、本番落とすことが多くてなかなか神経質になっていたから
コードをより注意深くみる癖がついたことによる発見だと思う。
気を抜いていたわけではなかったが、これからも継続していきたい