Follow up to post about invalid fallback values
Published 4 months agoDiscussing how you can use the type system to your advantage to avoid passing around values that don't make sense. How types alone aren't enough to ensure your value is "valid", and response to my previous post's feedback on Reddit.
Yesterday, I wrote an article about invalid fallback values, often combined with the ?? operator in TypeScript. I then decided to post it on Reddit /r/programming, and received what I can only describe as very mixed feedback. In the end, the post ended with 0 points, and only 30% upvoted it. I will begin this post by addressing some of the comments, as I believe some of them are very valid points, and some of them I disagree with.

For the first time, I got some actual traffic to the website. Over 600 unique visitors visited on the 21st of November. It was very exciting to see that people were engaging with my content.
Firstly, a number of people commented on the choice of name, which originally (and still is on Reddit as I can't change it) was "Abuse of the nullish coalescing operator in JS/TS". The thought behind the title, originally, was to talk about a pattern I often see in TS codebases where that operator in particular is frequently used as a quick fix to remove the nullability of a variable. Some people thought that abuse was a too strong word, and that I agree on. I later changed it on my website, but on reddit that wasn't possible. Others said that that had nothing to do with ?? operator, and while I understand the point they're making, I chose to talk about this one as it's the one I see used for this the most frequently.
That being said, and as someone else pointed out, the real concern the article was intended to address was the fact that a lot of people choose to use "" as a fallback value in the case of a nullable variable, rather than handle the null-case properly. Sometimes, "" is an OK fallback value, and that is a valid point, but the article was written for the cases where it is not.
I should have made that clearer, and perhaps by not focusing so explicitly on one operator used to achieve this, I would have succeeded in doing so. There are a million ways to make T|undefined or T|null into T in TypeScript. As I wrote in a comment, I have been working a lot with frontend code the recent years, and I think because of that, I've grown so accustomed to seeing the ?? "" as you can use it when passing down props in Svelte/React, or within the rendering templates themselves such as with <p>{user?.name ?? ""}</p>.
The most liked comment however, ended up being one that said: "This is a skill issue, can happen in any language." While I do agree with the last part, I did frankly find this comment a little discouraging. For me it's a type of comment that I see time and again on both HackerNews and reddit which doesn't really contribute to the conversation, but aims to leave the reader with the impression that the writer of the comment is too good to commit errors like that. The particular phrase "skill issue" I've watched emerge the last couple of years as yet another sarcastic comment which I've come to associate with the aforementioned forums. Of course the problem mentioned in the article is a "skill issue" in the sense that if you were to do it better you wouldn't write that code. But yet I find it written in codebases written by everything from AI to Juniors to Seniors. Deadlines, laziness, burnout and a million other factors can affect how you write code, and as this isn't by any means a cardinal sin, I think it's easy to let a few of these slip to simply get rid of the squiggly lines in your editor. If you're thinking about writing a comment like this, how about writing why you think people write this instead, and how it could be made easier to write the right thing or avoid the wrong one.
Anyways, I've always found the topic of types and sets of valid values to be very interesting. Ever since I first touched static typed languages with C++ quite a few years ago, I've never looked back. Types, however, do not provide some magical end-all be-all solution to the problem of data validation as I'm sure we all know. You might declare a variable uint status_code even though you know that it can only be the numbers 100-599. There are languages that have this, such as Ada with Subtype Predicates, but I haven't seen a widespread adoption yet. There are other patterns that can be used, such as defining a custom value class where you can implement more complex validation in a custom setter, but that moves us away from compile-time validation and into run-time.
Another related pattern I see, and quite like, is using type aliases to make the type of a variable more explicit — if only to the developer reading the code. For instance, defining type AreaCentimeters = float makes it very clear that the variable with that type uses centimeters, and not feet or other bodily measurements. You can then, depending on language and how you choose to represent this value type, for instance implement arithmetic for the type, creating functions that only take centimeters, and making AreaMeters variables incompatible with the functions.
Both of these are cool patterns, but I believe a lot can be achieved by relying on simple primitives like Option<T> or Result<T, E> types, and handling the absence of values gracefully. Handling options and results as high up as I can, and trying to the best of my abilities to write functions with simple signatures is a trick I've found to keep my code easier to read.
Failing early, as described in "Let it crash" and in the Erlang philosophy, albeit perhaps a more conservative approach, I've found to be of great help to writing resilient software that is easy to debug, monitor, and improve. By treating errors as first class citizens and having a very conscious relationship to them during development I've found results in easier and more maintainable code as well.