I just recently started refactoring my large scale angular app to Typescript's strict mode. Dealing with lots of null checks the question arose again if I should prefer using undefined
over null
or vice versa. A couple of thoughts:
- Is using
undefined
for initially undefined values and usingnull
whenever you want to unassign a value a good option? - Using
undefined
everywhere simplifies things at first, but then there is JSON (onlynull
available) and API responses. How to best deal with those? - How to best deal with pre-checks for when you are reasonably confident that a value is not
null
, but it theoretically could be (e.g. angular@Inputs
you always assign)? Do you prefer to typecast or do you use error checks?
I wonder how do you deal with the problem. Do you prefer one over the other? Do you use both? What's your take on it?
Latest comments (16)
I think null is for explicitly acknowledging that this has no value and if it's undefined it's a better indication of a bug / error / unhandled case.
A simple rule that I introduced in the previous company where I worked:
Always initialize variables with
null
, any encounteredundefined
was treated as an error.Typically, we'd only have
undefined
values when working with externally provided data, and we'd have validation logic on incoming data anyway, which took care of transforming it intonull
(or throwing an error, depending on which was appropriate).Simply put, a
null
is intentionally empty, anundefined
indicated that something wasn't 100% right.I use
undefined
is a abort in binding, for example in Web Atoms framework, we can create binding likeIn above case, this basically refreshes text whenever
a
b
orc
is modified, however, I can set any of it toundefined
to cancel the update operation. Update will occur only if all are notundefined
, this allow me to clearly distinguish betweenundefined
andnull
.You don't deal with
null
vsundefined
but you use it as one thing. The key is to use the concept ofnullish
. My few cents here - Maybe Just NullableWhen we write TypeScript apps, we tend to prefer using neither null nor undefined. We use null objects : let’s say you have a Customer to display. We use a const NoCustomer of same type to underline that there is no customer selected/in state at the moment. Leverage the power of typed languages ;)
Now you can say if(customer != NoCustomer) explicit, no doubt possible.
In JS I don't think in terms of null or undefined, but think in terms of "nil".
I use a utility func similar to Ramda's R.isNil.
And I have a complement func called, isNotNil
Source Code:
gist.github.com/funfunction/0e64a5...
Simple answer: Be consistent with their use in your code.
There are subtle differences, were one can have variable behavior from the other. However, in most cases it is personal preference.
There was some brief conversation on this very topic as part of a broader discussion with @addyosmani on a recent DevDiscuss episode...
Might help add a tiny bit of color to the conversation.
I just use undefined everywhere, and ruthlessly convert nulls to undefined as they come off an API.
I appreciate the difference. I'd sum it up as a nullable type being shorthand for a set with either zero or one item.
null
is just how we say the set has no entries, sonull
, in my head, has a type and is always used in the context of a nullable type.undefined
never has a type, it's just a void.But, I'm really not a fan of this kind of unneeded technical nuance. There are few cases IME where converting all the nulls to undefineds has broken my code, but having a source of undefineds sneak into a system I'd designed exclusively for nulls sounds like a day I'll never get back.
I get why someone would prefer to use
null
how it was designed, but I already make complex enough code, KISS has to be my mantra for this sort of thing.I consider the difference to be one of implicitly nonexistent (undefined) vs. explicitly having no value (null). A newly declared variable that has no initial value, vs. an array element that you've cleared, is a suitably illustrative example of the difference.
As for handling them, I consider casting without checks a strict no-no in strongly typed languages like TypeScript. Don't blindly cast... but DO check to make sure the operation you're attempting is valid if you can, and trap the error if you can't.
That's an excellent point! Thank you very much! How do you usually deal with (unexpectedly) failing type checks in these scenarios? Do you just throw an error?
Yep. I error (or skip if optional).