Null safety and the result type: Handling errors as values
In short: Modern languages make “no value” and “error” visible in the type (option, result, nullable types), so the compiler detects forgotten checks instead of things blowing up at runtime.
In more detail: The inventor of the null reference, Tony Hoare, called it his “billion-dollar mistake”: almost any value can suddenly be null, and forgotten checks lead to NullPointerException and TypeError. Newer languages model absence in the type system.
In Depth
Optional / nullable types
- Kotlin:
Stringcan never be null,String?can. The compiler forces a check:name?.length,name ?: "unknown". - TypeScript (
strictNullChecks):string | undefined, call with?.and??. - Swift:
String?(optional),if let,guard let. - Rust:
Option<T>withSome(x)orNone; no null. - Java:
Optional<T>, annotations (@Nullable), tools such as NullAway. - C#: nullable reference types (
string?). The error is discovered by the compiler, not only in operation.
Result type instead of exceptions
Instead of throwing exceptions, functions return a value containing success or error:
fn divide(a: f64, b: f64) -> Result<f64, String> {
if b == 0.0 { Err("division by zero".to_string()) }
else { Ok(a / b) }
}
match divide(1.0, 0.0) {
Ok(x) => println!("{}", x)
Err(e) => println!("Error: {}", e)
}Result exists in Rust, Swift, Kotlin (Result), Scala (Either), Haskell (Either) and can be rebuilt as a library in other languages. The error path is visible in the type and cannot be ignored.
Pros and cons
Advantages: safety (compiler checks), readability (expectable errors appear in the signature), no hidden jumps like with exceptions, easily chainable (map, and_then, the ? operator). Disadvantages: more writing effort, nesting without good syntax, for unexpected errors (memory full, programming errors) exceptions or panics remain sensible. Rule of thumb: expectable errors as values, programming errors as exceptions/abort.
In practice
Even without a new language: check inputs early, do not pass None/null around, use sensible defaults or the “null object” pattern, choose types precisely (int instead of int|null), enable strict in TypeScript. Document when a function can return nothing.
See also: NullPointerException, Exception handling, Cannot read properties of undefined