I find that as long as the code is reasonably straightforward, I get most of TS's benefits without actually declaring any types. It was kind of a pain to originally set up, but the code hints really are pretty magical.
/** @type {import('../index').Engine} */
this.engine = engine
Most of my projects have a god object at the center, so if I explicitly type that one object then I get basically all the important code hints for free.A side benefit of this is that you can also use TypeDoc to generate docs. It's not really made for vanilla JS, but once I got over the initial road bumps I've been happy with the results.
At this point the features that ts has and reason doesn't out number that of the other way around. I only know that reason has more stringent jsx types and opaque types (easily done in ts in 2 lines of code). On the other hand ts has mapped types and conditional types, weird as they are, pretty unique to itself. In the future, expect ts to be even more functional and absorb ideas from F# which is also from microsoft.
You can't do that with ReasonML, you are forced to adopt another language that is not Javascript.
For frontend it might be different, but as someone who usually touches the Js ecosystem through node, I pretty much won't use Js.
Like why should I give up insane utility with negligible (if any) runtime cost, high configurability (with sane defaults), easy buy in (since all Js is valid Ts)?
Maybe the last part is what you're missing? Most "layers on Js" needed you to rewrite or annotate all your code to get and value at all.
But you drop a tsconfig in a project and you instantly get value out of it. What past layer on Js had that?