DEV Community

Discussion on: You don't need null

 
scottshipp profile image
scottshipp

You should keep null in the surface of contact with things that "need" null

It sounds nice, but null is part of the JavaScript language itself. It has an explicit meaning in the specification:

primitive value that represents the intentional absence of any object value

So that "surface area" you're talking about isn't going to be limited to APIs. And when you share a JS codebase with anyone else, the approach of not using null is going to be untenable, and, even if you don't share, your JS is not going to be idiomatic.

 
loucyx profile image
Lou Cyx

I mean, I worked for years now with different teams without using null, and nobody misses it or says "we could solve this with null". I said it on the article already, but making that distinction between "intentionally absent" and "unintentionally absent" doesn't make sense, because is just "absent" and you need to deal with it the exact same way.

 
scottshipp profile image
scottshipp

I mean, I worked for years now with different teams without using null, and nobody misses it or says "we could solve this with null".

That doesn't mean it's idiomatic.

said it on the article already, but making that distinction between "intentionally absent" and "unintentionally absent" doesn't make sense, because is just "absent" and you need to deal with it the exact same way.

I can see that it doesn't make sense for you, but look at all the commenters here with plenty of examples where it makes sense. And I even gave you one in another thread.

 
loucyx profile image
Lou Cyx

If we have to use this article as a metric, we have 10+ negative comments and 10+ folks liking those comments, so let's say 20+ total. And then we have 55 likes to the article itself, 17 unicorns, and 6 positive comments, so let's say total 70+ ... I knew I would have some folks that wouldn't agree (that happens with every article in this series). You keep saying is not idiomatic, and my point is that you're just saying "the same thing with two different words". The distinction is not needed, you might use null to make that distinction between two "optional" values, but you don't need null for that.

The point of the article is to actually make you think if you need it, I know some of you are used to using null or you do that unnecessary distinction between null and undefined, but the idea is to make you actually think if you need that distinction, or not. Have you actually tried to code without using null yourself? Maybe you already did, and you missed null every single day, but my experience (and the experience of many other folks) was the exact opposite.

 
scottshipp profile image
scottshipp

You keep saying is not idiomatic, and my point is that you're just saying "the same thing with two different words".

The point about idiomatic JavaScript has to do with working with JavaScript developers. If you write in a non-standard (not idiomatic) way, you make it harder for others to use your code or integrate with it, and that can lead to bugs.

The point of the article is to actually make you think if you need it

These reasons to use null seem compelling to me:

  • null is core to the JavaScript language--it's in the language specification and used in various language features
  • null is returned from data sources, user input, and third-party libraries and API's whether or not your code uses it
  • As a result, null is idiomatic JavaScript (leading to the point above)
  • null has a different meaning from undefined, which is significant, and the two cannot be used as substitutes of each other without creating ambiguity (null is used to show that the value was explicitly set, undefined is used to indicate that no value was ever set)
 
loucyx profile image
Lou Cyx • Edited

The point about idiomatic JavaScript has to do with working with JavaScript developers. If you write in a non-standard (not idiomatic) way, you make it harder for others to use your code or integrate with it, and that can lead to bugs.

How can use less ""features"" makes something lead to bugs? The only way of leading to bugs is if a dev assumes that something will have a null value, for example, and my function returns undefined instead ... but the same could happen the other way around :/ (not to mention both are solved the exact same way)

null is core to the JavaScript language--it's in the language specification and used in various language features

Being in the language is not a "compelling" reason, because we avoid things in the language all the time that we know are bad. eval and with are still part of core JavaScript, and you wouldn't use those because you know that they lead to issues of all kinds.

null is returned from data sources, user input, and third-party libraries and API's whether or not your code uses it.

I already said that you can then deal with null only when working with those. Not to mention that data sources can also return undefined, it depends on how are they made, and the actual user input is never null, you can get "null" of user input only if the handler for said input returns null.

As a result, null is idiomatic JavaScript (leading to the point above)

So for you idiomatic is: It's in the language + folks use it. From that definition, being "idiomatic" is not a good reason to use something from my point of view.

null has a different meaning from undefined, which is significant, and the two cannot be used as substitutes of each other without creating ambiguity (null is used to show that the value was explicitly set, undefined is used to indicate that no value was ever set)

I keep asking why is that distinction even useful? They are both missing values, both needs to be handled the same way ... so why is useful to differentiate one from the other?

 
scottshipp profile image
scottshipp

How can use less ""features"" makes something lead to bugs? The only way of leading to bugs is if a dev assumes that something will have a null value, for example, and my function returns undefined instead ...

Exactly. Consider the matches() method on string. It returns null to indicate that there are no matches found. Let's say we take your approach and wrap this in our own method where we return undefined for this case instead. Now you have a client of your method who is a JavaScript developer. They check for null to see if no matches were returned, but you have overwritten this with undefined. And that's a fairly benign case.

This is often known as the Principle of Least Astonishment or Surprise. Users of your code should have an expected experience.

 
loucyx profile image
Lou Cyx • Edited

Do you actually do if (matches === null) nowadays? You don't need a wrapper. You can use nullish coalescing and avoid a lot of pain with both null and undefined (again, you handle both cases the same way). So you can do something like this:

const [match] = "bar".match(/foo/) ?? [];

console.log(match ?? `Not found`);
Enter fullscreen mode Exit fullscreen mode

Which works with both null and undefined. Instead of having to write:

const matches = "bar".match(/foo/);

console.log(matches !== null && matches[0] !== undefined ? matches[0] : `Not found`);
// or relying on falsy
console.log(matches && matches[0] ? matches[0] : `Not found`);
Enter fullscreen mode Exit fullscreen mode

And I still don't see where the distinction between null and undefined is valuable here. With the same example of the util, if someone does a wrapper of something that generally returns undefined, and they make it return null, it could cause confusion as well. You should't code assuming the nullish output of a function, and you still can be resolved similarly to the above issue.

BTW, if I had to write a wrapper for match, I would do it something like this:

const match => regExp => string => string.match(regExp) ?? [];
Enter fullscreen mode Exit fullscreen mode

This way you can not only curry it, but always be sure you'll receive an ArrayLike from it instead of RegExpMatchArray | null which is far from ideal.

 
scottshipp profile image
scottshipp

Do you actually do if (matches === null) nowadays?

It seems that you asking this question proves the point. You have no idea what I (or other clients of your code) are going to do. I may do that or use the fact of matches returning null (and not undefined) in probably a few dozen different ways. And when/if you change that, you introduce the potential for bugs, as previously pointed out.

You don't need a wrapper.

The idea of a "wrapper" came from your comments, not mine, though.

And I still don't see where the distinction between null and undefined is valuable here. With the same example of the util, if someone does a wrapper of something that generally returns undefined, and they make it return null, it could cause confusion as well.

I am not sure but I'll give the benefit of the doubt here and assume that you are not willfully missing the point. So to reiterate again: yes that could cause confusion as well, and the very fact of this confusion is why JavaScript developers should not ask "Do I really need to use null?" and should, instead, use both null and undefined consistent with general practice. It is the standard practice (the idiom) in JavaScript for null to represent a purposefully-set value and undefined to represent a value that was never set, and this is in the language specification as well as the canonical books and documentation.

 
loucyx profile image
Lou Cyx

It seems that you asking this question proves the point.

My point was that you shouldn't assume the output of a function. In your previous comment you basically said that you "expect" something to return null. Based on your same logic in this new comment: "You have no idea what I (or other clients of your code) are going to do", so why is bad for me to assume you'll know that you shouldn't do matches === null, but is good for you to assume that the function will return null instead of actually checking the return type of the thing you're using?

And when/if you change that, you introduce the potential for bugs, as previously pointed out.

But that's the thing, if you use a function assuming it will return either null or undefined, why is it on me as the dev and not on you as the consumer of that function? I already said this, but the other way around your same argument applies, if you create a function that I expect will return undefined, and instead you decide that it will return null, then it's my problem that I was expecting your function to return something I wanted it to return, instead of checking the typing or using something like ??.

And I still don't see where the distinction between null and undefined is valuable here. With the same example of the util, if someone does a wrapper of something that generally returns undefined, and they make it return null, it could cause confusion as well.

I am not sure but I'll give the benefit of the doubt here and assume that you are not willfully missing the point.

Trust me, I'm giving you the same benefit. I added sources to the article for y'all to explore, because my personal experience of not using null in personal projects and at work, and not missing it at all, and explaining that the "distinction" between intentionally missing and unintentionally missing value is pointless because they are both missing and need to be dealt with the same way. Maybe checking some other sources besides my article adds some light to the subject, but if null is so necessary, how is it that Angular is considering dropping null, TypeScript doesn't use null in its source, and folks like Douglas Crockford, with years of experience in JS, don't use null at all and just use undefined instead?

As @darkwiiplayer pointed out several times already, that "need" for multiple nullish values is trivial, having 1, 2 or 10 different nullish values with differences you define with conventions, doesn't take back the fact that they are all still just nullish.

Every time I ask: Why do you need to do that distinction?

The answer is pretty much "because null exist in JavaScript for that", but that doesn't actually answer the question. There are several things that exist in JS to be used for something, and we realized that there are better ways to do that same thing and not use that feature (eval and with are the two that I mention constantly).

We might never agree on this, but the questions I leave to you are:

Do you actually tried to code without null at any point? Do you ever worked with a library/framework or codebase without null and missed having it? Because I sure did tried doing it "your way" in the past, and once I did the "transition" I never went back.

Some comments have been hidden by the post's author - find out more