To further explain what’s happening, the maximum integer in ReScript is a 32 bit integer, whereas the JavaScript number type is 64 bits. ReScript enforces the 32 bit limit by appending a | 0 after every integer (In JS, all bitwise operators like | are 32 bit, so this automatically converts it).
In regular JS code, you probably aren’t adding | 0 to enforce the 32 bit limit, which is why the overflow isn’t happening. As @kevanstannard mentioned, using floats instead is the easiest way around the limit.
The reason they use 32-bit integers is that ReScript inherits the type system of OCaml. In OCaml, the standard int type is 32 bits. There is also a float type, which resembles the number type in JavaScript, along with an int64 type, which is 64 bits, but very different from float.
The bottom line is that ReScript isn’t changing the core type system or semantics of OCaml, which it is based on. They have made several patches to make things easier for JS interop (like uncurried function types), but most things remain the same.