Documentation Index
Fetch the complete documentation index at: https://mintlify.com/effect-TS/effect-smol/llms.txt
Use this file to discover all available pages before exploring further.
The Option module provides a type-safe way to represent values that may or may not exist. An Option<A> is either Some<A> (containing a value) or None (representing absence).
Mental Model
Option<A> is a discriminated union: None | Some<A>
None represents the absence of a value (like null/undefined, but type-safe)
Some<A> wraps a present value of type A, accessed via .value
- Monad: chain operations with
flatMap, compose pipelines with pipe
- Immutable: all operations return new
Option values; the input is never mutated
- Yieldable: in
Effect.gen, producing the inner value or short-circuiting with NoSuchElementError
Key Operations
Create
Build Options from values:
import { Option } from "effect"
// From a value
const some = Option.some(42)
// { _tag: "Some", value: 42 }
// Absent value
const none = Option.none()
// { _tag: "None" }
// From nullable
const fromNull = Option.fromNullishOr(null) // None
const fromValue = Option.fromNullishOr(42) // Some(42)
// From iterable (first element)
const fromArray = Option.fromIterable([1, 2, 3]) // Some(1)
const fromEmpty = Option.fromIterable([]) // None
// From throwing function
const parse = Option.liftThrowable(JSON.parse)
const ok = parse('{"x": 1}') // Some({ x: 1 })
const err = parse("invalid") // None
Check
Test and narrow:
import { Option } from "effect"
const value: Option<number> = Option.some(42)
// Type guards
if (Option.isSome(value)) {
console.log(value.value) // 42 (type narrowed to Some<number>)
}
if (Option.isNone(value)) {
// Type narrowed to None<number>
}
// Generic check
const isOption = Option.isOption(value) // true
Map and chain:
import { Option } from "effect"
const value = Option.some(5)
// Map (transform the value)
const doubled = Option.map(value, (n) => n * 2)
// Some(10)
// FlatMap (chain operations)
const result = Option.flatMap(value, (n) =>
n > 0 ? Option.some(n * 2) : Option.none()
)
// Some(10)
// Replace value
const replaced = Option.as(value, "hello")
// Some("hello")
Unwrap
Extract the value:
import { Option } from "effect"
const some = Option.some(42)
const none = Option.none<number>()
// With fallback
const value1 = Option.getOrElse(some, () => 0) // 42
const value2 = Option.getOrElse(none, () => 0) // 0
// To null/undefined
const asNull = Option.getOrNull(none) // null
const asUndef = Option.getOrUndefined(none) // undefined
// Throw on None
try {
const value = Option.getOrThrow(none) // throws Error
} catch (e) {
console.log(e.message) // "getOrThrow called on a None"
}
// Custom error
try {
const value = Option.getOrThrowWith(none, () => new Error("Missing"))
} catch (e) {
console.log(e.message) // "Missing"
}
Match
Pattern match:
import { Option } from "effect"
const value: Option<number> = Option.some(42)
const message = Option.match(value, {
onNone: () => "No value",
onSome: (n) => `Value is ${n}`
})
// "Value is 42"
Filter
Refine values:
import { Option } from "effect"
const value = Option.some(5)
// Filter with predicate
const positive = Option.filter(value, (n) => n > 0)
// Some(5)
const negative = Option.filter(value, (n) => n < 0)
// None
// Filter and map
const evenDoubled = Option.filterMap(value, (n) =>
n % 2 === 0 ? Option.some(n * 2) : Option.none()
)
// None (5 is odd)
Combine
Join multiple Options:
import { Option } from "effect"
const name = Option.some("Alice")
const age = Option.some(30)
// Zip into tuple
const pair = Option.zipWith(name, age, (n, a) => ({ name: n, age: a }))
// Some({ name: "Alice", age: 30 })
// Combine all (tuple)
const tuple = Option.all([name, age])
// Some(["Alice", 30])
// Combine all (struct)
const struct = Option.all({ name, age })
// Some({ name: "Alice", age: 30 })
// Any None makes result None
const withNone = Option.all([name, Option.none()])
// None
Fallback
Provide alternatives:
import { Option } from "effect"
const primary = Option.none<string>()
const fallback = Option.some("default")
// Return fallback if None
const result1 = Option.orElse(primary, () => fallback)
// Some("default")
// Wrap fallback value
const result2 = Option.orElseSome(primary, () => "default")
// Some("default")
// First Some from iterable
const first = Option.firstSomeOf([
Option.none(),
Option.some(1),
Option.some(2)
])
// Some(1)
Convert
To/from other types:
import { Option, Result } from "effect"
// From Result
const okResult = Result.succeed(42)
const success = Option.getSuccess(okResult) // Some(42)
const errResult = Result.fail("error")
const failure = Option.getFailure(errResult) // Some("error")
// To array
const someArray = Option.toArray(Option.some(1)) // [1]
const noneArray = Option.toArray(Option.none()) // []
Generator
Compose with generator syntax:
import { Option } from "effect"
const result = Option.gen(function* () {
const a = yield* Option.some(2)
const b = yield* Option.some(3)
const c = yield* Option.none() // Short-circuits here
return a + b + c // Never reached
})
// None
const success = Option.gen(function* () {
const a = yield* Option.some(2)
const b = yield* Option.some(3)
return a + b
})
// Some(5)
Do Notation
Build objects step-by-step:
import { Option, pipe } from "effect"
const result = pipe(
Option.Do,
Option.bind("x", () => Option.some(2)),
Option.bind("y", () => Option.some(3)),
Option.let("sum", ({ x, y }) => x + y)
)
// Some({ x: 2, y: 3, sum: 5 })
Type Signatures
// Core types
type Option<A> = None<A> | Some<A>
interface None<A> {
readonly _tag: "None"
}
interface Some<A> {
readonly _tag: "Some"
readonly value: A
}
// Creation
const some: <A>(value: A) => Option<A>
const none: <A = never>() => Option<A>
const fromNullishOr: <A>(a: A) => Option<NonNullable<A>>
// Guards
const isOption: (input: unknown) => input is Option<unknown>
const isNone: <A>(self: Option<A>) => self is None<A>
const isSome: <A>(self: Option<A>) => self is Some<A>
// Transform
const map: {
<A, B>(f: (a: A) => B): (self: Option<A>) => Option<B>
<A, B>(self: Option<A>, f: (a: A) => B): Option<B>
}
const flatMap: {
<A, B>(f: (a: A) => Option<B>): (self: Option<A>) => Option<B>
<A, B>(self: Option<A>, f: (a: A) => Option<B>): Option<B>
}
// Unwrap
const getOrElse: {
<B>(onNone: () => B): <A>(self: Option<A>) => B | A
<A, B>(self: Option<A>, onNone: () => B): A | B
}
const getOrThrow: <A>(self: Option<A>) => A
// Match
const match: {
<B, A, C = B>(options: {
readonly onNone: () => B
readonly onSome: (a: A) => C
}): (self: Option<A>) => B | C
}
See Also
- Result — For operations that can fail with an error
- Effect — For async/effectful computations
- Array — Working with collections of Options