5 ms·
Disagree on #10. The amount of code I've seen that intentionally distinguishes between null and undefined is... well, zero. On the other hand, the amount of c
by recursive 6y ago
Disagree on #10. The amount of code I've seen that intentionally distinguishes between null and undefined is... well, zero. On the other hand, the amount of code I've seen that unintentionally distinguishes between them when it shouldn't have is not zero.
- dvdhnt 6y agoHmm, not sure what you're saying exactly. Null and undefined are different. A common example would be any sort of patch operation - setting a value to null is valid, whereas if the value of that property is undefined, it likely should be ignored. Sorry if I am misunderstanding your statement.
- srcreigh 6y agoA concrete example of this is setState in React. T | null signifies that it can be cleared by using setState({prop: null}). T | undefined means that it may start out undefined, but if it becomes defined it'll probably stay that way. If you try doing setState({prop: undefined}), it won't work.
- recursive 6y agoThere doesn't seem to be any fundamental reason why that had to be the case. I'm not a react expert, but it seems like it would have been more obvious to me if null and undefined were treated the same. The distinction should be whether the key exists in the object.
- presentation 6y agoIt's a poor design carried over from legacy JavaScript, but there are clear differences at the language level. While not the only one, the biggest one to me is this kind of code: const x = {}; x.foo // returns undefined const y = { foo: undefined }; y.foo // also undefined Basically a member not being provided will return undefined, whereas `null` had to actually be set. Hence I think the tendency for checking for the absence of something via `undefined`, while expressing the deletion of something with `null`. Sure, you can assert more specific types in TypeScript to step around that, or you can do something less intuitive like checking for `keyof` to detect absence; but this is both straightforward and presents less issues when interfacing with inputs from non-typescript-using users.
- rfw300 6y agoI think what he’s saying is not that there is no semantic difference between the two, but that in practice programmers use the two so interchangeably that not checking for both is likely to cause more trouble than it’s worth.
- lopatin 6y agoYes plz. No one wants to know the difference between those two. Of course, you still do need to. But don't make the problem worse by writing code breaks when you mistake one for the other.
- Normal_gaussian 6y agoWelcome to any of my codebases. Undefined and null have clear semantic differences, and those differences are important to the function, safety, and performance of the code.
- patrickthebold 6y agoCurious: Roughly, how many people work on those code bases?
- recursive 6y agoThat's perfectly fine. If you need to distinguish between them, then you should do that. There's plenty of code that's different though. I would say probably most of it. The semantic differences seem to be local at best. In any case, there's plenty of code that legitimately doesn't concern itself with any of that.
- spinningarrow 6y agoAn example of where the distinction is quite important - default parameters for functions only work when the argument is undefined.
- recursive 6y agoWhat do you mean by "work"? If you assign a default parameter value, you never need to mention undefined or null.
- BigJono 6y ago'work' as in if you explicitly pass in undefined as a parameter to a function, the default parameter will be used in it's stead. I've never ever run into this because I never use undefined for anything other than stuff that's explicitly not set, and I have no fucking idea why other people are. But I can definitely see it causing bugs if you do stuff like use '!=' everywhere and treat null and undefined as the same thing. This is why the original comment is wrong. You should be narrowing your types where possible. It costs nothing to just always use null if you're explicitly setting something, then you can use '!==' wherever you want, which means that if someone else sets something to undefined you'll catch the bug straight away when it's easiest to catch. If you treat them the same you're just asking for some 3rd party lib to do a '!== null' or accidentally overwrite a "null" with a default parameter you're not expecting, and that's way, way harder to troubleshoot.
- recursive 6y agoI've never run into this, because I never explicitly pass an expression when I want the default parameter value to be used. You could just as easily run into a bug with 3rd party lib code by distinguishing between the two when that library doesn't. The only reason I've ever intentionally used `null` in my own code is that it precedes `undefined` in the default array sort. But if I ever found myself using library code that required `null` for something, I'd say "Huh. That's weird." And then I'd pass it a `null`.
- 6y ago
- throwoutttt 6y agoUndefined and null should be treated differently. null: the value exists but is not set. undefined: the value does not exist. JSON.stringify on an undefined property removes that property. JSON.stringify on null keeps that property as null. A codebase that does not distinguish between null and undefined is a less flexible codebase.
- bikeshaving 6y agoTrying to finely parse the semantics of null and undefined like this is a fool’s errand, insofar as there isn’t much in the language which enforces your conventions. Also, these conventions fall apart when we check how null is actually used. For instance, all DOM nodes have a default of null for their first children and next siblings. Does this mean “the value exists but is not set?” What does it mean when the browser is setting the value and not the user? At the end of the day it would have been much nicer for there to only have been one nothing type but what’s done is done.
- chrismorgan 6y agoElement.foo being undefined says “foo? What’s foo? I don’t know what you’re talking about.” Element.{firstChild, nextSibling} being null means “I know what firstChild (or nextSibling) is, but this element doesn’t have one.” It would be categorically wrong for things like Element.{firstChild, nextSibling} to be undefined.
- bikeshaving 6y agoSome developers would interpret your rule as being, if it doesn’t make sense for you to make this property access on this specific object, the value should resolve to undefined and not null. Problem is, there already are mechanics for a kind of check like you describe (the in operator and hasOwnProperty both kinda do what you’re looking for). Moreover, if you were to design the DOM API from scratch, by your logic some developers might assume that text nodes, which never have children, should have a firstChild set to undefined and not null, because it should say “I don’t know what you’re talking about.” You can debate this last point, but know that some people are going to interpret the null/undefined rules as you describe in this way. I’ve seen null/undefined semantics play out; they more or less collapse under the slightest of deadline pressures or scaling of team sizes. There are infinite ways to splice the idea of “emptiness” or “lack of data” and any definition you provide (the definitions both you and OP provide give a lot of wiggle room) would be interpreted fifteen ways by fifteen developers, so much so that even changing hands just once will cause any null/undefined distinctions to sublimate in any codebase. There are so many languages which do just fine with one null type; I don’t understand why JavaScript developers have to do these sorts of mental kinesthetics to justify the existence of two in JavaScript, especially given the more or less insane fact that `typeof null === "object"`. If you consistently use undefined or null exclusively internally, and accept both via the == null trick externally, you can pretty much avoid having to deal with null/undefined semantics entirely.
- SomeCallMeTim 6y agoTotally agree with you. Some of the rebuttals below seem to be saying "But I use them differently!" Bully for them, but 99% of the time when it's not set, you don't really care why it's not set because it's not defined yet or because it's been set to `null`. And any time they assume it can only be null OR undefined but not either, there's a chance for a bug. Even if I "know" it can only ever be null and not undefined, it's safer to just say != null rather than !== null. Treating them differently in a code base is a legit semantic, but testing with != null works no matter the intended semantics.
- SkyPuncher 6y agoIMO, the last 3 should really just be "be explicit when it matters". I see more room for error with being explicit as a default than generalizing as a default.
- WA 6y agoYes, I disagree on #10 as well. Because: createNewMessagesResponse(null) 'You have null new messages' Of course, TypeScript will say that 'null' can't be passed to createNewMessagesResponse directly. However, data gets pushed around a code base a lot and might go through third party packages or come in from an API response and could very well be 'null'. I proactively don't check for 'undefined', because I can't really trust this to be 'undefined'. Furthermore, in the example OP provided, 'null' and 'undefined' should have the same result (no message is shown, because no number was passed to the function).