Use explicit nullable types
Put null
into the type system where it belongs, and reap
the benefits.
Several years of Hack and Flow projects have convinced me that
explicit nullable types are the correct design for a language with
null
.
That is, the language treats (for example) string
and
?string
as two different types, making it a compile-time
error to dereference a ?string
before checking for null.
Goodbye, null reference exceptions.
The best implementations of this do type refinement, where
the type checker will locally upgrade a ?T
to a
T
inside of a null check, using static analysis to prove,
where it can, that the value is locally non-null. For example, in
Hack:
$thing = maybeAString(); // $thing is ?string
if ($thing is nonnull) {
doSomethingWith($string); // $thing is string
}
Once you’ve experienced this feature, you will consider it insane
that you ever lived without it. It stands to reason: null
is not a T
; it’s the absence of a T
! Why
should you be allowed to treat it as a T
? All of your new
code in statically-typed languages should be making use of this to the
extent your language allows.
For functional programmers
In languages like Rust, Elm, Haskell, OCaml, Mint, or anything else
with algebraic data
types and pattern matching, you don’t have to worry about this; your
“null” is already part of your type system in the form of a
Maybe
monad or something like it. Broadly speaking, you
don’t get null reference crashes in these languages.