* 'readonly' support, while nice to have, is mostly broken. It's just way too easy to coerce a readonly value into a non-readonly one, especially with nested objects.
* There are no proper sum types. You can emulate tagged unions with a type field as a tag and match on that and get good compiler support for the fields, but in no way does it feel like a proper, language-supported sum type.
* Javascript semantics leak through to TS all the time. Which is kind of the point, TS is supposed to be a static typing layer on top of JS.
This is an advantage too: you stay close to the actual runtime and it's easy to interact with non-typescript code.
But a lot of stuff still feels quite messy, like a bolted on abstraction (which it is).
> * 'readonly' support, while nice to have, is mostly broken. It's just way too easy to coerce a readonly value into a non-readonly one, especially with nested objects.
Do you have any example of this? To be honest, as much as I'd love immutability support built into the language, the number of bugs I get from accidentally mutating data is so low it's not something I would make a lot of effort to get. There's always Object.freeze as well which will throw an error if you try to violate immutability.
> * Javascript semantics leak through to TS all the time. Which is kind of the point, TS is supposed to be a static typing layer on top of JS.
Does this not happen in BuckleScript/Reason as well at the layer where you interface with JavaScript libraries?
> But a lot of stuff still feels quite messy, like a bolted on abstraction (which it is).
Yeah...it's practical though and has an easy plus incremental migration path. Switching to OCaml would be much bumpier.
If you have some time, please give that intro page a read. Hopefully that intro page explains what we're achieving. If you'd like more nuanced opinions, we're always in Discord (discord.gg/reasonml).
1. I feel like I shouldn't feel ashamed when saying this, but here: mutation, imperative code & side-effect are kinda nice, and very much needed for a straightforward interop with e.g. existing JS/Obj-C/Java (hint hint) code. For example, notice how BS externals are erased & inlined. Most of our ffi doesn't have a conversion cost. An excellent ffi can be a deal maker, considering that if you're serious about migrating your codebase to a new language, you'd be using more ffi than idiomatic code for a while. Early on, I've had folks accidentally modify the output JS artifacts on messenger.com because they thought I wrote the JS code myself; they were generated by BS.
2. Also, speaking of native compilation: we're not reference counting but _some_ predictability when working with UI code is needed. The GC has to be fast and collect things within 16ms (and now, 8ms since iPad Pro is often 120fps). The ocaml gc achieves that.
Those aren't my findings: those are the findings of the creator of React, who also created Reason.
3. Finally, and to corroborate with what we wrote on that page: if you go ask your "normal JS colleagues", you'll realize most folks don't _actually_ know the semantics of JS. They like JS because it _looks_ familiar. Is TypeScript "just JavaScript"? Does it matter if JS folks can pick it up and be equally productive quickly? OCaml/BS semantics map over to JS well enough that we can just change the syntax into something familiar, and you'd likey end up writing the code you'd usually write in JS, albeit backed by a type system that needs to make no excuse in terms of quality.
Hope that helps? Tell me if that makes sense.
(Tail recursion has been a problem for a single person so far afaik; you do have imperative loops)
> I feel like I shouldn't feel ashamed when saying this, but here: mutation, imperative code & side-effect are kinda nice, and very much needed for a straightforward interop with e.g. existing JS/Obj-C/Java (hint hint) code.
Similar feelings...OCaml has mutability built in but you don't need it often. You can isolate its use to small areas of your code to keep it under control. If you went the Haskell route getting JS developers to adopt would be even harder.
> Also, speaking of native compilation: we're not reference counting but _some_ predictability when working with UI code is needed.
So the GC is well behaved with Reason scripts? I'm curious if you could use it for games.
Thanks for the insights. I haven't heard of Reason much to be honest which is a shame. I used OCaml as my main language for several years and going back to Java, Python and JavaScript was pretty painful!
Yeah. Some existing algorithms are more easily expressed with mutability, and for FFI it's very needed; I think some community-wide messaging regarding this is good enough. Constraining them at the type level might make adoption a bit harder.
We're just a syntax for OCaml; we don't change how it runs. Same GC. Reason's mMuch less sophisticated than you think, but also much fewer unknowns. https://reasonml.github.io/try/
The goal of Reason (and of BuckleScript) is so that people can convince their coworkers that OCaml isn't an esoteric unmaintainable language. BuckleScript is JavaScript: The Good Parts: The Good Parts.
TypeScript doesn't support deep readonly, which would be really helpful for Redux, where you're required to copy anything you change, but can easily forget.
When I tried Typescript briefly, it seemed like the compiler was surprisingly slow. Not super slow, just nothing at all like writing raw JS directly, or Python or anything like that.
This blog post emphasizes that BuckleScript compiles very quickly. Sounds very appealing.
* 'readonly' support, while nice to have, is mostly broken. It's just way too easy to coerce a readonly value into a non-readonly one, especially with nested objects.
* There are no proper sum types. You can emulate tagged unions with a type field as a tag and match on that and get good compiler support for the fields, but in no way does it feel like a proper, language-supported sum type.
* Javascript semantics leak through to TS all the time. Which is kind of the point, TS is supposed to be a static typing layer on top of JS.
This is an advantage too: you stay close to the actual runtime and it's easy to interact with non-typescript code.
But a lot of stuff still feels quite messy, like a bolted on abstraction (which it is).