Every codebase has values that might not be there. A user without a middle name. A search that finds nothing. A config key nobody set. The question is how your code says so.
With null references, it doesn't say anything. Any value could be missing, and you find out at runtime (see Null References). An Option type puts the answer in the type itself. `Option<User>` tells every reader, and the compiler, that there might be no user. `User` alone means there is always one.
**How it works**:
An Option is a small sum type with two variants (see Algebraic Data Types):
- `Some(value)`: the value is present
- `None`: the value is absent
To get the value out, you have to handle both cases, usually with pattern matching. Forget the `None` branch, and the code doesn't compile.
**Where you'll find it**:
- **Rust**: `Option<T>`, used throughout the standard library
- **Haskell**: `Maybe a`, with `Just x` and `Nothing`
- **OCaml, F#, Scala, Elm**: `option` / `Option` / `Maybe`
- **Swift**: `Optional<T>`, written `T?`
- **Java**: `Optional<T>` since Java 8, mostly meant for return values
Kotlin, C# and TypeScript (with `strictNullChecks`) take a related approach: nullable types like `String?` that the compiler tracks.
**Working with Options**:
You rarely take a value out of an Option by hand. Most languages give you combinators that keep the code flat:
- **`map`**: transform the value if it's there, keep `None` otherwise
- **`flatMap` / `and_then`**: chain steps that can each return nothing
- **`unwrap_or` / `orElse`**: provide a default when the value is absent
- **`filter`**: turn `Some` into `None` when a condition fails
**Watch out**:
Every Option type has an escape hatch that pulls the value out without checking: `unwrap()` in Rust, `get()` in Java, `fromJust` in Haskell. Used on a `None`, it crashes, exactly like a null would. Reach for it only when you can prove the value exists, and keep it rare enough to search for.
Also keep in mind that Option means "might be absent", nothing more. When you need to say WHY something is missing (e.g., "not found" vs. "permission denied"), use a `Result` or `Either` type instead.
**Why it matters**:
The Option type is Make Illegal States Unrepresentable applied to absence. A value that can't be missing isn't marked as optional, so you never check it. A value that can be missing is marked, so you never forget.