If your program typechecked against Netscape Navigator in 1997, does that prove that it will run without type errors in AwesomeNewBrowser 2023?
IMO null/undefined/etc are reasonable fallbacks if your runtime environment can radically diverge from its static model.
Option<T> types which can have either Some(value) or Nothing for values. Statically compiled languages can typecheck this so you don’t have null pointer errors.
Some languages like TypeScript have this baked into the language syntax, so you can do: let x: Foo | null = bar; and is also properly type checked.
E.g. it’s perfectly fine to say you might have an empty value via ‘Foo | null’ or ‘Foo?’ or with something like null, ‘Maybe Foo’ but to sneak it into plain old ‘Foo’ is problematic (a billion dollars worth of problems).
Option/Maybe monads are one option popular in static functional languages.
For set oriented languages, an empty set is an option. (This is very similar to the previous option, actually.)
Null is kind of a middle ground between these options and a ad hoc use of a specific sentinel value like using a signed integer variable when the data is logically unsigned, so you can use “-1” for missing data.
So I guess the better question is how do you express the idea of skipping checking for Sentinel when the language always checks for sentinel?
data Maybe a = Nothing | Just aThe only reason why you may need null is to check whether a reference is null. You remove this need by forbidding it in well defined programs.
"It is by far the most problematic part of language design. And it's a single value that -- ha ha ha ha -- that if only that wasn't there, imagine all the problems we wouldn't have, right? If type systems were designed that way. And some type systems are, and some type systems are getting there, but boy, trying to retrofit that on top of a type system that has null in the first place is quite an undertaking." -Anders Hejlsberg