median blog

Comparing Nullable<T> in Typescript to Option<T> in Rust

On the surface, Nullable<T> and Option<T> seem similar. Their definitions are:

type Nullable<T> = T | null

type Option<T> = Some(T) | None

The issue I have seen is that Nullable<T> is happy with a null no matter where it came from. Noting here that Nullable isn't part of the Typescript stdlib but it is common.

As an example, the following Typescript is valid (V5.3.3 tested on the typescript playground).

type Nullable<T> = T | null;

function foo(x : Nullable<number>) {
  if (x === null) {
      console.log("Is Null");
  }
}

let x : Nullable<string> = null;

foo(x);

On the other hand, the following rust will not compile. (Tested locally on Rust Stable).

fn foo(x: Option<i32>) {
    if x.is_none() {
        println!("Is None");
    }
}

fn main() {
    let x: Option<String> = None;

    foo(x);
}

Looking at the two of those, the Rust result seems more correct to me. If we are parsing optional data from user input, a null is not always the same. Type safety to me comes form not putting things in the wrong box.

That's not to say there's no path to an Option<T> equivalent in Typescript but Nullable<T> is not a drop in replacement.