Thank you for sharing this benchmark.
Getting a slower runtime by porting to ReScript contradicts my experience, so I inspected your implementation.
Most of the runtime difference is caused by unnecessary indirection by Option.flatMap and Option.forEach in hot loops, the additional cost of Array.prototype.forEach, and the early return difference.
After switching Option.flatMap to inline pattern-matching and forEach() to a while loop with early return, I got performance on par with the TypeScript version.
One tip is that if you rewrite all the loops as recursive functions, the compiler will pre-optimize tail recursion and automatically change it into a while loop ahead of time. Then you can visually identify which parts of the entire loop are already optimized and which are not.
Of course, for-loop and control-flow improvements are one of the major milestones of ReScript.