I would assume almost all of us here agree that more type safety is better. Static code analysis, handling edge cases and having the compiler tell you “hey, you didn’t handle this particular case…” is generally a good thing. For most of my code, I feel ReScript is helping reduce the amount of bugs I would otherwise introduce into the code. Although I consider myself rather smart, and although I’ve been coding for a quarter of a century, I make so many mistakes. Thanks, ReScript.
But there are times when ReScript no longer wants to be my friend - times when it becomes a tyrannical boss instead. Although ReScript is coherent and logical - in the end, I am smarter and more experienced. And perhaps most importantly, I know better than ReScript when it’s time to be pragmatic about things.
The doc makes a silly example of this:
// Dom access can actually fail. ReScript
// is really explicit about handling edge cases!
switch(ReactDOM.querySelector("#root")){
| Some(root) => ReactDOM.render(<div> {React.string("Hello Andrea")} </div>, root)
| None => () // do nothing
}
From: Rendering Elements | React
To me, ReScript being so explicit about handling edge cases as in the example provided above is not helpful. First of all, I have never, ever, ever had the ReactDOM.querySelector call fail.
Actually, that’s a lie. It has happened. I’ve named the root element incorrectly, or forgot to put it in there. So maybe ReScript is helpful here, after all?
No way!. If the querySelector call fails and returns nothing, nothing in my app is going to work, it’s not even going to render. Ask yourself which is more helpful, a blank screen or everything blowing up with error messages? Ten times out of ten, I want things to crash and burn with error messages if the entire app is unable to function. ReScript forcing you to do simple “hacks” to get it to shut up is causing you to write bad solutions here, introducing problems that will take more of your time. Let’s say you open your app, and it “does nothing.” Your browser shows a blank screen. Where do you even begin to debug your shit to finally realize that you had named the root element incorrectly? Good luck with that - that can potentially be an entire day’s worth of work out the window. If ReScript instead would let things blow up, I could fix it within minutes. I don’t think I’m exaggerating here.
Hey, this does not mean ReScript is bad. It’s great - I love it. But there needs to be a lower threshold for escape-hatching. I think we should reason about escape-hatching as were it an analog scale, from zero where everything is without types (hello, JavaScript) and “forcibly typed” where there aren’t any escape hatches.
A default typeless setting is obviously a bad idea. We’ve tried that, it makes your code full of bugs (hello, Javascript).
I would argue the opposite is as bad. It forces you into idiotic solutions as the one above. “oh I need to handle this case that might happen one time out of a million, ah crap, that’s never gonna happen, let me just put a no-op on it”. How is that better?
I think what I’m trying to communicate is there might be a need to “lower the threshold” for escape-hatching a bit. I think it’s a matter of finding the sweetspot where it’s tedious enough that you don’t do it as soon as you encounter a situation as the one above, but where it’s simple enough that you don’t put no-ops just to get the compiler to work with you.
Here’s another, less serious example:
...
{if isAdmin {
<ul> {adminItems->renderSidebarItems} </ul>
} else {
<> </>
}}
...
Putting the else
part there is tedious and annoying. JSX is already doing all sorts of hocus pocus behind the scenes, it might as well do it for cases like that as well. It makes my code more neat, shorter, makes me have to type less and in no way introduces any more errors.
I think there is a certain level of pragmatism required here, and we should probably spend some more time thinking about it. There’s generally a fear of ad-hoc’ing solutions in the compiler for known cases, but maybe that would be the right thing to do. Yeah, ReScript would become a bit warty - but it already is in other ways and we might as well look to develop an environment that is helpful as much as it can be rather than being a software implementation of Putin.
Give me your thoughts on this.