Skip to content

Option Handling Utility

A lightweight utility for handling potentially nullable or undefined values without resorting to null checks all over your codebase. Inspired by the Option type in languages like Rust, this utility encourages explicit handling of optional values and avoids runtime errors due to undefined or null.

Types

Option<T>

Discriminated union of Some<T> and None. This allows you to explicitly model optional values.

ts
export type Option<T> = Expand<Some<T>> | Expand<None>

Some<T>

Represents the presence of a value.

ts
export interface Some<T> {
    kind: "some"
    value: T
}

None

Represents the absence of a value.

ts
export interface None {
    kind: "none"
}

Expand<T>

Ensures the returned object is fully expanded (not a type alias).

ts
type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never

Factory Function

option(val?: T | null)

Wraps a potentially nullable value into an Option<T>.

ts
const maybeUser = option(user)
  • Returns Some<T> if value is not null or undefined
  • Returns None otherwise

$option Utility

Wrap an Option<T> value to gain access to fluent methods.

ts
const $opt = $option(maybeUser)

.isSome / .isNone

Check which kind of Option it is.

ts
if ($opt.isSome) doSomething($opt.unwrap())

.map(fn)

Transform the wrapped value if it's present.

ts
$opt.map((user) => user.name)

.flatMap(fn)

Chain operations that also return Option.

ts
$opt.flatMap((user) => option(user.profile))

.unwrap()

Retrieve the value, or throw if it's None.

ts
const user = $opt.unwrap() // throws if none

.unwrapOr(fallback)

Retrieve the value, or provide a fallback.

ts
const user = $opt.unwrapOr(defaultUser)

.match({ some, none })

Explicit branching based on whether value is present.

ts
$opt.match({
    some: (user) => greet(user.name),
    none: () => showLogin(),
})

Benefits

  • ✅ Eliminates null/undefined bugs
  • ✅ Makes optional values explicit
  • ✅ Easy to chain and transform safely
  • ✅ Better observability than bare booleans
  • ✅ Can pair well with Result types for robust error + null handling

Use Case Example

ts
function findUser(id: string): Option<User> {
    const user = db.get(id)
    return option(user)
}

const $user = $option(findUser("123"))

$user.match({
    some: (u) => console.log("Hello", u.name),
    none: () => console.log("User not found"),
})

This utility enforces explicit handling of maybe-values. You’ll never forget to check for null again — because you can’t.