LoginSignup
7
1

More than 1 year has passed since last update.

GraphQLのScalerのIntが32bitの理由を調べた話

Last updated at Posted at 2021-12-14

この記事は、Supershipグループ Advent Calendar 2021の14日目の記事になります。

はじめに

The Int scalar type represents a signed 32‐bit numeric non‐fractional value. Response formats that support a 32‐bit integer or a number type should use that type to represent this scalar.

GraphQLのScalerのIntは32bitと定義されてあり、いまどきにしては扱える数値の範囲が狭い理由が何故なのかが気になり、調べた話です。

graphql-spec

It wasn't included because it's not available across all platforms, most importantly and practically in our case: JavaScript.

graphql-specの過去のissueによると、すべてのプラットフォーム(JavaScript)で利用できないからというコメントがありました。

JavaScriptのNumber

検証環境はChromeの96.0.4664.93です。

JavaScriptのNumberは安全に扱える整数の上限のNumber.MAX_SAFE_INTEGERが定義されてます。
JavaScriptのNumberはIEEE754なのでその辺の精度の話になります。

Number.MAX_SAFE_INTEGER // 9007199254740991 

安全に扱えるってどうゆうことなのか

Number.MAX_SAFE_INTEGERより大きい値を使って比較した例です

9007199254740992 === 9007199254740993 // true

この場合は数値が違うのでfalseになるのが正しいようにみえますが、丸められてしまってtrueになってしまいます。

GraphQL APIがJSONでNumber.MAX_SAFE_INTEGERより大きい値を返した来た場合どうなるのか

バックエンドはGraphQLでフロントエンドがReactやVueなどのJavaScriptのフレームワークでWebアプリケーションを作ってる場合、 Apollo ClientのようなGraphQLクライアントでAPIから値を取得してから使うことになりますが、その場合はHTTPのレスポンスボディで返るJSONの文字列をJavaScriptのオブジェクトに変換するのにJSON.parseする必要が出ます。

JSON.parse(`{"value": 90071992547409918712}`) // {value: 90071992547409920000}

Number.MAX_SAFE_INTEGERより大きい値が入ってる状態でJSON.parseすると9007199254740991871290071992547409920000になってしまい数値が変わってしまいました。

このJavaScriptオブジェクトを使ってしまうと、APIが返してる数値と違う数値を使ってしまうことが起こるので気をつける必要があります。

まとめ

Number.MAX_SAFE_INTEGERを超えた場合の整数を正しく扱う場合は以下のことを気をつける必要がありそうです。

  • 該当するGraphQLのフィールドのScalerをIntからStringに変更する
  • JavaScriptで比較や演算する場合はBigIntを使う

最後に

Supershipではプロダクト開発やサービス開発に関わる人を絶賛募集しております。
ご興味がある方は以下リンクよりご確認ください。
Supershipグループ 採用サイト
是非ともよろしくお願いします。

7
1
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
7
1