There is quite a lot of inherent complexity of web as a platform. If frameworks were any more abstracted they would be too brittle for a lot of use cases.
Btw, use Sorbet for Ruby static typing. It's very ergonomic.
We adopted Sorbet for our codebase a couple of months ago, and I couldn't be happier with that choice. Sure, it's not as powerful as Typescript (e.g. no way to specify a union of constants like `type Result = 'ok' | 'error'`), but it's worth it just for the nil-check alone. And it's great for documenting too. It's easy to forget what type a method expects for its parameters.