4 ms·
I agree with most of these, but I pretty strongly disagree with #10 (don't use `!= null`). The reasoning is that you can use `null` and `undefined` to mean diff
by dlbucci 6y ago
I agree with most of these, but I pretty strongly disagree with #10 (don't use `!= null`). The reasoning is that you can use `null` and `undefined` to mean different things, like `null` being "no first name" and `undefined` meaning "haven't asked yet". I agree that strict TS lets you do stuff like that fairly easily, but I think this is a really bad idea, because there's nothing that would indicate to a reader of that code the meaning of `null` vs `undefined` for those properties.
I feel in that case you should have some type union of `"notAsked" | "none" | { t: "some", v: "Name" }`, because that would be more clear of what each possible value means. Let `null` and `undefined` be synonyms for `nil`.
- codefined 6y agoI've been regularly trying to reduce / remove usage of `null` in various projects. Sindresorhus has some interesting discussions on the topic here[0]. [0] https://github.com/sindresorhus/meta/discussions/7 https://github.com/sindresorhus/meta/discussions/7
- Normal_gaussian 6y agoI strongly advocate for using both BUT not propagating undefined. That is to say, use null and handle undefined. You'll need to write undefined as a potential type for potentially undefined object members, and as such it means exactly that - undefined. For everything else there is null. A sanity check would be - undefined can only appear in a function parameter type or object member type as a union with other types, or in a === comparison. For everything else there is null.
- mdtusz 6y agoThe way I always see it is that `null` is for known unknowns, and `undefined` is for unknown unknowns. Explicitly defining something as `undefined` is paradoxical and IMO should never be done. I've tried to explain this concept to some co-workers without much lasting success, but it's a pretty common concept to other languages. Undefined should basically never be used as a value directly.
- mantap 6y agoIt's funny, I have a policy of the opposite. Use undefined, don't propagate null. map.get("missingKey") returns undefined. The new ?. operator returns undefined, even if you pass it null. Undefined means that you don't have to care about the difference between { foo: undefined } and { }. The only pain point is that JSON.parse() produces null, but this is relatively easy to work around. I don't find any reason to ever produce a null. I just treat it as a value that can occur when using certain APIs. If your code depends on the difference between a missing key and a missing value, probably you should be using a Map which makes that difference explicit with separate set() and delete() methods.
- worldsayshi 6y agoThis why I don't fully agree with #2. I often avoid default assignment because it only works for undefined and not null (or was it the other way around?) which can be surprising and cause hard to find bugs. || allow falling back from either. Should be used with some care though. I used to use || more frivolously.
- odshoifsdhfs 6y agoYeah I agree. I actually created a `type Optional<T> = T | null` for one of my projects because I wanted a good way to describe something that is null vs undefined. This is specially important if you are de/serialising objects. In my case, undefined = user did nothing to it, null = user actually chose not to supply value (and yes, they are different)