This is somewhat helpful in seeing implementation details but I was wondering why we do things this way, it is just to achieve a cleaner syntax or is there some deeper meaning behind it?
Oh, OK. Well at its core, ReScript is a functional programming language. So basically it uses modules, types, and functions to express the equivalent concepts that OOP languages would express with classes and methods.
Gotcha so this is something inherit in FP, it would be helpful in a beginner’s guide to ReScript to include a snippet about this since someone transitioning from an OOP approach (such as myself) would probably be confused why this approach is used and why something like str.substring() just straight up doesn’t exist.
There is some good news - in the time since the Js modules were written ReScript added something called “records as objects”. The effect of this is that for simple properties we can use records do property access like arr.length (although not for Array since it’s a built-in type). For functions like str.substring() this approach isn’t recommended due to runtime implications, but that’s getting a bit beyond the scope of your question.
I don’t know if the existing types can be converted to use records without breaking existing applications, but I find it quite useful in my own custom bindings.
No, because Js.Array2.length(arr) compiles to arr.length in JS.
To answer the “why,” it may help to think about how functional languages like ReScript keep data separate from the functions that use data. In an OOP language like JavaScript, you may be used to data carrying around various properties or methods which allow you to do stuff with it. In ReScript, the data is just data, and you do everything with functions.
Because the compiler targets JS, it automatically compiles some functions into object property access (i.e. Js.Array2.length(arr) -> arr.length), but that’s just a special feature of the compiler. The language itself doesn’t have a concept of properties the same way that JS does.
(Yes, there are record and object types with fields similar to JS objects, but they don’t use all of the OOP features that built-in JS types have.)