Option
Option<A> models a value that may be absent. It is either Some<A>, holding a
value of type A, or None, representing no value. Use it instead of
null/undefined when absence is a normal, expected outcome — looking up a key,
parsing input, reading an optional field. The type then makes the missing case
visible and the compiler forces you to handle it.
import { Option } from "effect"
// A partial function: defined only for non-empty arraysconst head = <A>(array: ReadonlyArray<A>): Option.Option<A> => array.length > 0 ? Option.some(array[0]) : Option.none()
// Handle both cases explicitly — no `undefined` checks leaking downstreamconst describe = <A>(array: ReadonlyArray<A>): string => Option.match(head(array), { onNone: () => "the array is empty", onSome: (value) => `the first element is ${value}` })
console.log(describe([1, 2, 3])) // "the first element is 1"console.log(describe([])) // "the array is empty"head returns an Option rather than A | undefined, so every caller must
decide what to do when the value is missing. Option.match is the safe way to
do that: it takes one callback per case and returns a single value.
Creating an Option
Section titled “Creating an Option”import { Option } from "effect"
const value = Option.some(1) // { _id: 'Option', _tag: 'Some', value: 1 }const empty = Option.none() // { _id: 'Option', _tag: 'None' }Option.none() is a function call (not a constant) so it can infer the element
type at the use site.
To build an Option from a predicate, use Option.liftPredicate:
import { Option } from "effect"
// ┌─── (n: number) => Option<number>// ▼const parsePositive = Option.liftPredicate((n: number) => n > 0)
console.log(parsePositive(10)) // { _id: 'Option', _tag: 'Some', value: 10 }console.log(parsePositive(-1)) // { _id: 'Option', _tag: 'None' }Modeling optional fields
Section titled “Modeling optional fields”Use Option<A> for properties that may have no value. The key is always
present; only the value is optional, which is exactly what Option expresses.
import { Option } from "effect"
interface User { readonly id: number readonly username: string // The `email` key is always present; the value may be absent readonly email: Option.Option<string>}
const withEmail: User = { id: 1, username: "john_doe", email: Option.some("john.doe@example.com")}
const withoutEmail: User = { id: 2, username: "jane_doe", email: Option.none()}Transforming and chaining
Section titled “Transforming and chaining”Option.map transforms the value inside a Some and leaves a None untouched.
Option.flatMap is for functions that themselves return an Option, letting
you walk nested optional data without manual checks.
import { Option } from "effect"
interface Address { readonly city: string readonly street: Option.Option<string>}interface User { readonly address: Option.Option<Address>}
const user: User = { address: Option.some({ city: "New York", street: Option.some("123 Main St") })}
// If `address` is None, the chain short-circuits to None.// Otherwise we dig into the nested optional `street`.const street = user.address.pipe( Option.flatMap((address) => address.street))
console.log(street) // { _id: 'Option', _tag: 'Some', value: '123 Main St' }Option.filter keeps the value only if a predicate holds, turning it into
None otherwise:
import { Option } from "effect"
// Treat an empty string as "no value"const nonEmpty = (input: Option.Option<string>) => Option.filter(input, (value) => value !== "")
console.log(nonEmpty(Option.some(""))) // { _id: 'Option', _tag: 'None' }console.log(nonEmpty(Option.some("a"))) // { _id: 'Option', _tag: 'Some', value: 'a' }Extracting the value
Section titled “Extracting the value”To get a plain value back out, supply a fallback so the None case is always
handled:
import { Option } from "effect"
// Provide a default for the None caseconsole.log(Option.getOrElse(Option.some(5), () => 0)) // 5console.log(Option.getOrElse(Option.none(), () => 0)) // 0
// Interop with code that expects null / undefinedconsole.log(Option.getOrNull(Option.none())) // nullconsole.log(Option.getOrUndefined(Option.some(5))) // 5
// Throws if None — use only at boundaries where None is truly impossibleconsole.log(Option.getOrThrow(Option.some(10))) // 10Fallbacks
Section titled “Fallbacks”Option.orElse tries an alternative when the first Option is None, and
Option.firstSomeOf returns the first Some from a list:
import { Option } from "effect"
const fromCache = Option.none<number>()const fromDb = Option.some(42)
console.log(Option.orElse(fromCache, () => fromDb))// { _id: 'Option', _tag: 'Some', value: 42 }
console.log( Option.firstSomeOf([Option.none(), Option.some(2), Option.some(3)]))// { _id: 'Option', _tag: 'Some', value: 2 }Interop with nullable values
Section titled “Interop with nullable values”Option.fromNullishOr converts null/undefined into None, and any other
value into Some. It is the bridge between Effect code and APIs that return
nullable values.
import { Option } from "effect"
console.log(Option.fromNullishOr(null)) // { _id: 'Option', _tag: 'None' }console.log(Option.fromNullishOr(undefined)) // { _id: 'Option', _tag: 'None' }console.log(Option.fromNullishOr(1)) // { _id: 'Option', _tag: 'Some', value: 1 }Going the other way, Option.getOrNull / Option.getOrUndefined turn a None
back into null / undefined.
Combining multiple Options
Section titled “Combining multiple Options”Option.all combines several Options into one, preserving the input shape
(tuple, struct, or iterable). If any input is None, the result is None.
import { Option } from "effect"
const maybeName: Option.Option<string> = Option.some("John")const maybeAge: Option.Option<number> = Option.some(25)
// ┌─── Option<{ name: string; age: number }>// ▼const struct = Option.all({ name: maybeName, age: maybeAge })console.log(struct)// { _id: 'Option', _tag: 'Some', value: { name: 'John', age: 25 } }
// One None makes the whole thing Noneconsole.log(Option.all([Option.some("John"), Option.none()]))// { _id: 'Option', _tag: 'None' }To combine two values with a function, use Option.zipWith.
Generator syntax
Section titled “Generator syntax”Like Effect.gen, Option.gen lets you write sequential code that
short-circuits on the first None. Each yield* either unwraps a Some or
aborts the whole block.
import { Option } from "effect"
const maybeName = Option.some("John")const maybeAge = Option.some(25)
const person = Option.gen(function* () { const name = (yield* maybeName).toUpperCase() const age = yield* maybeAge return { name, age }})
console.log(person)// { _id: 'Option', _tag: 'Some', value: { name: 'JOHN', age: 25 } }If maybeName were None, the generator would stop immediately and return
None — age would never be read. Keep these generators pure: Option is a
data structure, not an effect, so avoid side effects inside them.
Interop with Effect
Section titled “Interop with Effect”An Option can be used directly inside Effect.gen. A Some<A> yields its
value; a None fails the effect with a NoSuchElementError, which you can then
handle with the usual Error Management combinators.
import { Effect, Option } from "effect"
const program = Effect.gen(function* () { // `yield*` on a Some produces the value; // a None would fail with NoSuchElementError const x = yield* Option.some(10) const y = yield* Option.some(5) return x + y})
Effect.runPromise(program).then(console.log) // 15This makes Option a convenient way to express “may be missing” steps inside an
otherwise effectful workflow.
API reference
Section titled “API reference”Most combinators are dual: they accept either data-first
(Option.map(self, f)) or data-last (self.pipe(Option.map(f))) call styles.
The examples below mix both. Items that return a Result cross-reference the
Result data type.
Constructors & guards
Section titled “Constructors & guards”Wraps a present value in Some. Does not filter null/undefined.
import { Option } from "effect"
console.log(Option.some(1))// => { _id: 'Option', _tag: 'Some', value: 1 }Creates the absent None. It is a function call so the value type infers at the
use site (e.g. Option.none<number>()).
import { Option } from "effect"
console.log(Option.none<number>())// => { _id: 'Option', _tag: 'None' }isOption
Section titled “isOption”Type guard for any Option (either Some or None), useful at runtime
boundaries.
import { Option } from "effect"
console.log(Option.isOption(Option.some(1))) // => trueconsole.log(Option.isOption({})) // => falseisSome
Section titled “isSome”Type guard narrowing an Option<A> to Some<A> so you can read .value.
import { Option } from "effect"
const o = Option.some(1)console.log(Option.isSome(o) ? o.value : "absent") // => 1isNone
Section titled “isNone”Type guard narrowing an Option<A> to None<A>.
import { Option } from "effect"
console.log(Option.isNone(Option.none())) // => trueconsole.log(Option.isNone(Option.some(1))) // => falsePattern matching & refinement
Section titled “Pattern matching & refinement”Handles both branches in one expression, returning a plain value.
import { Option } from "effect"
console.log( Option.match(Option.some(1), { onNone: () => "empty", onSome: (value) => `value: ${value}` }))// => "value: 1"toRefinement
Section titled “toRefinement”Turns an Option-returning function into a type guard (returns true when the
function yields Some). Useful for Array.prototype.filter.
import { Option } from "effect"
const parseString = (x: string | number): Option.Option<string> => typeof x === "string" ? Option.some(x) : Option.none()
const isString = Option.toRefinement(parseString)console.log(isString("a")) // => trueconsole.log(isString(1)) // => falseliftPredicate
Section titled “liftPredicate”Converts a Predicate (or Refinement) into an Option-returning function:
Some(value) when it holds, None otherwise.
import { Option } from "effect"
const positive = Option.liftPredicate((n: number) => n > 0)console.log(positive(1)) // => { _id: 'Option', _tag: 'Some', value: 1 }console.log(positive(-1)) // => { _id: 'Option', _tag: 'None' }From other types
Section titled “From other types”fromIterable
Section titled “fromIterable”Wraps the first element of an iterable in Some, or None when empty. Only the
first element is consumed.
import { Option } from "effect"
console.log(Option.fromIterable([1, 2, 3])) // => { _id: 'Option', _tag: 'Some', value: 1 }console.log(Option.fromIterable([])) // => { _id: 'Option', _tag: 'None' }fromNullishOr
Section titled “fromNullishOr”Treats both null and undefined as None; any other value becomes
Some (typed NonNullable<A>).
import { Option } from "effect"
console.log(Option.fromNullishOr(null)) // => { _id: 'Option', _tag: 'None' }console.log(Option.fromNullishOr(undefined)) // => { _id: 'Option', _tag: 'None' }console.log(Option.fromNullishOr(1)) // => { _id: 'Option', _tag: 'Some', value: 1 }fromUndefinedOr
Section titled “fromUndefinedOr”Treats only undefined as None, leaving null as a valid Some.
import { Option } from "effect"
console.log(Option.fromUndefinedOr(undefined)) // => { _id: 'Option', _tag: 'None' }console.log(Option.fromUndefinedOr(null)) // => { _id: 'Option', _tag: 'Some', value: null }fromNullOr
Section titled “fromNullOr”Treats only null as None, leaving undefined as a valid Some.
import { Option } from "effect"
console.log(Option.fromNullOr(null)) // => { _id: 'Option', _tag: 'None' }console.log(Option.fromNullOr(undefined)) // => { _id: 'Option', _tag: 'Some', value: undefined }liftNullishOr
Section titled “liftNullishOr”Lifts a function that may return null/undefined into one returning Option
(wraps the result via fromNullishOr).
import { Option } from "effect"
const parse = (s: string): number | undefined => { const n = parseFloat(s) return isNaN(n) ? undefined : n}const parseOption = Option.liftNullishOr(parse)console.log(parseOption("1")) // => { _id: 'Option', _tag: 'Some', value: 1 }console.log(parseOption("nope")) // => { _id: 'Option', _tag: 'None' }liftThrowable
Section titled “liftThrowable”Lifts a function that may throw into one returning Option: normal return →
Some, thrown exception → None.
import { Option } from "effect"
const parse = Option.liftThrowable(JSON.parse)console.log(parse("1")) // => { _id: 'Option', _tag: 'Some', value: 1 }console.log(parse("")) // => { _id: 'Option', _tag: 'None' }getSuccess
Section titled “getSuccess”Converts a Result to an Option, keeping the success
value and discarding the failure.
import { Option, Result } from "effect"
console.log(Option.getSuccess(Result.succeed("ok"))) // => { _id: 'Option', _tag: 'Some', value: 'ok' }console.log(Option.getSuccess(Result.fail("err"))) // => { _id: 'Option', _tag: 'None' }getFailure
Section titled “getFailure”Converts a Result to an Option, keeping the failure
value and discarding the success.
import { Option, Result } from "effect"
console.log(Option.getFailure(Result.fail("err"))) // => { _id: 'Option', _tag: 'Some', value: 'err' }console.log(Option.getFailure(Result.succeed("ok"))) // => { _id: 'Option', _tag: 'None' }Unwrapping & extraction
Section titled “Unwrapping & extraction”getOrElse
Section titled “getOrElse”Returns the Some value, or lazily evaluates a fallback thunk on None.
import { Option } from "effect"
console.log(Option.getOrElse(Option.some(1), () => 0)) // => 1console.log(Option.getOrElse(Option.none(), () => 0)) // => 0getOrNull
Section titled “getOrNull”Returns the Some value, or null on None.
import { Option } from "effect"
console.log(Option.getOrNull(Option.some(1))) // => 1console.log(Option.getOrNull(Option.none())) // => nullgetOrUndefined
Section titled “getOrUndefined”Returns the Some value, or undefined on None.
import { Option } from "effect"
console.log(Option.getOrUndefined(Option.some(1))) // => 1console.log(Option.getOrUndefined(Option.none())) // => undefinedgetOrThrow
Section titled “getOrThrow”Returns the Some value, or throws a generic Error on None.
import { Option } from "effect"
console.log(Option.getOrThrow(Option.some(1))) // => 1// Option.getOrThrow(Option.none())// => throws Error: getOrThrow called on a NonegetOrThrowWith
Section titled “getOrThrowWith”Returns the Some value, or throws the value produced by onNone() on None.
import { Option } from "effect"
console.log(Option.getOrThrowWith(Option.some(1), () => new Error("missing"))) // => 1// Option.getOrThrowWith(Option.none(), () => new Error("missing"))// => throws Error: missingFallbacks
Section titled “Fallbacks”orElse
Section titled “orElse”Returns self if Some; otherwise lazily evaluates the fallback Option.
import { Option } from "effect"
console.log(Option.orElse(Option.none(), () => Option.some("b"))) // => { _id: 'Option', _tag: 'Some', value: 'b' }console.log(Option.orElse(Option.some("a"), () => Option.some("b"))) // => { _id: 'Option', _tag: 'Some', value: 'a' }orElseSome
Section titled “orElseSome”Like orElse, but the fallback is a plain value that is automatically wrapped
in Some.
import { Option } from "effect"
console.log(Option.orElseSome(Option.none(), () => "b")) // => { _id: 'Option', _tag: 'Some', value: 'b' }orElseResult
Section titled “orElseResult”Returns the first available value wrapped in a Result so
you can tell whether it came from the primary (Failure) or fallback
(Success).
import { Option } from "effect"
console.log(Option.orElseResult(Option.some("primary"), () => Option.some("fallback")))// => { _id: 'Option', _tag: 'Some', value: { _id: 'Result', _tag: 'Failure', failure: 'primary' } }console.log(Option.orElseResult(Option.none(), () => Option.some("fallback")))// => { _id: 'Option', _tag: 'Some', value: { _id: 'Result', _tag: 'Success', success: 'fallback' } }firstSomeOf
Section titled “firstSomeOf”Returns the first Some in an iterable of Options, or None if all are
None. Short-circuits on the first Some.
import { Option } from "effect"
console.log(Option.firstSomeOf([Option.none(), Option.some(1), Option.some(2)]))// => { _id: 'Option', _tag: 'Some', value: 1 }Transforming & sequencing
Section titled “Transforming & sequencing”Transforms the value inside a Some, leaving None unchanged.
import { Option } from "effect"
console.log(Option.map(Option.some(2), (n) => n * 2)) // => { _id: 'Option', _tag: 'Some', value: 4 }console.log(Option.map(Option.none<number>(), (n) => n * 2)) // => { _id: 'Option', _tag: 'None' }Replaces the Some value with a constant, preserving presence/absence.
import { Option } from "effect"
console.log(Option.as(Option.some(42), "x")) // => { _id: 'Option', _tag: 'Some', value: 'x' }asVoid
Section titled “asVoid”Replaces the Some value with undefined (Option<void>).
import { Option } from "effect"
console.log(Option.asVoid(Option.some(42))) // => { _id: 'Option', _tag: 'Some', value: undefined }Option.void is a pre-built Some(undefined) constant for the same purpose.
flatMap
Section titled “flatMap”Applies a function returning an Option and flattens the result; None skips
the function.
import { Option } from "effect"
console.log(Option.flatMap(Option.some(2), (n) => Option.some(n * 2)))// => { _id: 'Option', _tag: 'Some', value: 4 }console.log(Option.flatMap(Option.none<number>(), (n) => Option.some(n)))// => { _id: 'Option', _tag: 'None' }andThen
Section titled “andThen”Flexible chaining: the next step can be a plain value, an Option, or a
function returning either. Plain values are wrapped in Some.
import { Option } from "effect"
console.log(Option.andThen(Option.some(5), (x) => Option.some(x * 2))) // => { _id: 'Option', _tag: 'Some', value: 10 }console.log(Option.andThen(Option.some(5), "hello")) // => { _id: 'Option', _tag: 'Some', value: 'hello' }flatMapNullishOr
Section titled “flatMapNullishOr”flatMap combined with fromNullishOr: chains a function that may return
null/undefined (great for optional-chaining property access).
import { Option } from "effect"
interface Employee { company?: { address?: { street?: { name?: string } } } }const emp: Employee = { company: { address: { street: { name: "high st" } } } }
console.log( Option.flatMapNullishOr(Option.some(emp), (e) => e.company?.address?.street?.name))// => { _id: 'Option', _tag: 'Some', value: 'high st' }flatten
Section titled “flatten”Removes one layer of nesting from Option<Option<A>>.
import { Option } from "effect"
console.log(Option.flatten(Option.some(Option.some("v")))) // => { _id: 'Option', _tag: 'Some', value: 'v' }console.log(Option.flatten(Option.some(Option.none()))) // => { _id: 'Option', _tag: 'None' }zipRight
Section titled “zipRight”Sequences two Options, keeping the second value when both are Some.
import { Option } from "effect"
console.log(Option.zipRight(Option.some(1), Option.some("hello"))) // => { _id: 'Option', _tag: 'Some', value: 'hello' }console.log(Option.zipRight(Option.none(), Option.some("hello"))) // => { _id: 'Option', _tag: 'None' }zipLeft
Section titled “zipLeft”Sequences two Options, keeping the first value when both are Some.
import { Option } from "effect"
console.log(Option.zipLeft(Option.some("hello"), Option.some(1))) // => { _id: 'Option', _tag: 'Some', value: 'hello' }console.log(Option.zipLeft(Option.some("hello"), Option.none())) // => { _id: 'Option', _tag: 'None' }composeK
Section titled “composeK”Kleisli composition: combines two Option-returning functions into one,
short-circuiting on the first None.
import { Option } from "effect"
const parse = (s: string) => (isNaN(Number(s)) ? Option.none() : Option.some(Number(s)))const double = (n: number) => (n > 0 ? Option.some(n * 2) : Option.none())const parseAndDouble = Option.composeK(parse, double)
console.log(parseAndDouble("42")) // => { _id: 'Option', _tag: 'Some', value: 84 }console.log(parseAndDouble("nope")) // => { _id: 'Option', _tag: 'None' }Runs a side-condition Option-returning function; keeps the original value if
it returns Some, otherwise becomes None.
import { Option } from "effect"
const getInteger = (n: number) => (Number.isInteger(n) ? Option.some(n) : Option.none())
console.log(Option.tap(Option.some(1), getInteger)) // => { _id: 'Option', _tag: 'Some', value: 1 }console.log(Option.tap(Option.some(1.5), getInteger)) // => { _id: 'Option', _tag: 'None' }filter
Section titled “filter”Keeps the value only when a predicate (or refinement) holds; otherwise None.
import { Option } from "effect"
console.log(Option.filter(Option.some("hello"), (s) => s !== "")) // => { _id: 'Option', _tag: 'Some', value: 'hello' }console.log(Option.filter(Option.some(""), (s) => s !== "")) // => { _id: 'Option', _tag: 'None' }filterMap
Section titled “filterMap”Transforms and filters at once via a Filter callback
that returns a Result: Result.succeed keeps the mapped value, Result.fail
discards it.
import { Option, Result } from "effect"
console.log( Option.filterMap(Option.some(2), (n) => n % 2 === 0 ? Result.succeed(`Even: ${n}`) : Result.failVoid ))// => { _id: 'Option', _tag: 'Some', value: 'Even: 2' }partitionMap
Section titled “partitionMap”Splits a Some into a [left, right] pair using a function returning a
Result: a Failure goes left, a Success goes right.
import { Option, Result } from "effect"
const parse = (s: string) => isNaN(Number(s)) ? Result.fail("not a number") : Result.succeed(Number(s))
console.log(Option.partitionMap(Option.some("42"), parse))// => [ { _id: 'Option', _tag: 'None' }, { _id: 'Option', _tag: 'Some', value: 42 } ]console.log(Option.partitionMap(Option.some("abc"), parse))// => [ { _id: 'Option', _tag: 'Some', value: 'not a number' }, { _id: 'Option', _tag: 'None' } ]reduceCompact
Section titled “reduceCompact”Folds an iterable of Options into a single value, skipping every None.
import { Option, pipe } from "effect"
const items = [Option.some(1), Option.none(), Option.some(2)]console.log(pipe(items, Option.reduceCompact(0, (b, a) => b + a))) // => 3toArray
Section titled “toArray”Converts an Option to an array: [value] for Some, [] for None.
import { Option } from "effect"
console.log(Option.toArray(Option.some(1))) // => [ 1 ]console.log(Option.toArray(Option.none())) // => []Combining
Section titled “Combining”product
Section titled “product”Combines exactly two Options into Some([a, b]) when both are present.
import { Option } from "effect"
console.log(Option.product(Option.some("hello"), Option.some(42)))// => { _id: 'Option', _tag: 'Some', value: [ 'hello', 42 ] }console.log(Option.product(Option.none(), Option.some(42)))// => { _id: 'Option', _tag: 'None' }productMany
Section titled “productMany”Combines a primary Option with an iterable of same-typed Options into a
non-empty tuple; any None yields None.
import { Option } from "effect"
console.log(Option.productMany(Option.some(1), [Option.some(2), Option.some(3)]))// => { _id: 'Option', _tag: 'Some', value: [ 1, 2, 3 ] }Combines a tuple, struct, or iterable of Options, preserving the input shape.
Any None makes the whole result None.
import { Option } from "effect"
console.log(Option.all([Option.some("John"), Option.some(25)]))// => { _id: 'Option', _tag: 'Some', value: [ 'John', 25 ] }console.log(Option.all({ name: Option.some("John"), age: Option.some(25) }))// => { _id: 'Option', _tag: 'Some', value: { name: 'John', age: 25 } }zipWith
Section titled “zipWith”Combines two Options using a function; None if either is absent.
import { Option } from "effect"
console.log(Option.zipWith(Option.some(2), Option.some(3), (a, b) => a + b))// => { _id: 'Option', _tag: 'Some', value: 5 }Lifts a binary function so it operates on two Options.
import { Option } from "effect"
const add = Option.lift2((a: number, b: number) => a + b)console.log(add(Option.some(2), Option.some(3))) // => { _id: 'Option', _tag: 'Some', value: 5 }console.log(add(Option.some(2), Option.none())) // => { _id: 'Option', _tag: 'None' }Predicates & search
Section titled “Predicates & search”contains
Section titled “contains”Tests whether a Some holds a value equal to the given one, using default
structural equality.
import { Option } from "effect"
console.log(Option.contains(Option.some(2), 2)) // => trueconsole.log(Option.contains(Option.some(1), 2)) // => falseconsole.log(Option.contains(Option.none(), 2)) // => falsecontainsWith
Section titled “containsWith”Like contains, but using a custom Equivalence.
import { Equivalence, Option } from "effect"
const check = Option.containsWith(Equivalence.strictEqual<number>())console.log(check(Option.some(2), 2)) // => trueconsole.log(check(Option.some(1), 2)) // => falseexists
Section titled “exists”Tests whether the value in a Some satisfies a predicate (or refinement);
None is always false.
import { Option } from "effect"
const isEven = (n: number) => n % 2 === 0console.log(Option.exists(Option.some(2), isEven)) // => trueconsole.log(Option.exists(Option.some(1), isEven)) // => falseconsole.log(Option.exists(Option.none(), isEven)) // => falseEquivalence & order
Section titled “Equivalence & order”makeEquivalence
Section titled “makeEquivalence”Builds an Equivalence for Option<A> from one for A. Two Nones are equal;
Some and None differ.
import { Equivalence, Option } from "effect"
const eq = Option.makeEquivalence(Equivalence.strictEqual<number>())console.log(eq(Option.some(1), Option.some(1))) // => trueconsole.log(eq(Option.some(1), Option.some(2))) // => falseconsole.log(eq(Option.none(), Option.none())) // => truemakeOrder
Section titled “makeOrder”Builds an Order for Option<A> from one for A. None sorts before any
Some.
import { Number as N, Option } from "effect"
const ord = Option.makeOrder(N.Order)console.log(ord(Option.none(), Option.some(1))) // => -1console.log(ord(Option.some(1), Option.none())) // => 1console.log(ord(Option.some(1), Option.some(2))) // => -1Do-notation & generators
Section titled “Do-notation & generators”The starting point for a do-notation chain: an Option of an empty record.
import { Option, pipe } from "effect"
console.log( pipe( Option.Do, Option.bind("x", () => Option.some(2)), Option.bind("y", () => Option.some(3)) ))// => { _id: 'Option', _tag: 'Some', value: { x: 2, y: 3 } }bindTo
Section titled “bindTo”Names the value of an existing Option, producing a single-key record — an
alternative entry point to Do.
import { Option, pipe } from "effect"
console.log(pipe(Option.some(2), Option.bindTo("x")))// => { _id: 'Option', _tag: 'Some', value: { x: 2 } }Adds an Option value to the do-notation record; a None short-circuits the
whole chain.
import { Option, pipe } from "effect"
console.log( pipe( Option.Do, Option.bind("x", () => Option.some(2)), Option.bind("y", () => Option.none<number>()) ))// => { _id: 'Option', _tag: 'None' }Adds a computed plain (non-Option) value to the do-notation record.
import { Option, pipe } from "effect"
console.log( pipe( Option.Do, Option.bind("x", () => Option.some(2)), Option.let("double", ({ x }) => x * 2) ))// => { _id: 'Option', _tag: 'Some', value: { x: 2, double: 4 } }Generator-based syntax: each yield* unwraps a Some or short-circuits to
None; the return value is wrapped in Some.
import { Option } from "effect"
const person = Option.gen(function* () { const name = (yield* Option.some("John")).toUpperCase() const age = yield* Option.some(25) return { name, age }})console.log(person)// => { _id: 'Option', _tag: 'Some', value: { name: 'JOHN', age: 25 } }Reducers & combiners
Section titled “Reducers & combiners”These advanced helpers build Reducer/Combiner instances for aggregating
collections of Options.
makeReducer
Section titled “makeReducer”Builds a Reducer that prioritizes the first non-None value and combines two
Somes with the given Combiner (initial value None).
import { Number, Option } from "effect"
const reducer = Option.makeReducer(Number.ReducerSum)console.log(reducer.combineAll([Option.some(1), Option.none(), Option.some(2)]))// => { _id: 'Option', _tag: 'Some', value: 3 }makeCombinerFailFast
Section titled “makeCombinerFailFast”Builds a Combiner with fail-fast semantics: any None operand yields None.
import { Number, Option } from "effect"
const combiner = Option.makeCombinerFailFast(Number.ReducerSum)console.log(combiner.combine(Option.some(1), Option.some(2))) // => { _id: 'Option', _tag: 'Some', value: 3 }console.log(combiner.combine(Option.some(1), Option.none())) // => { _id: 'Option', _tag: 'None' }makeReducerFailFast
Section titled “makeReducerFailFast”Lifts an existing Reducer into one over Option with fail-fast semantics
(initial value Some(reducer.initialValue)); any None aborts the result.
import { Number, Option } from "effect"
const reducer = Option.makeReducerFailFast(Number.ReducerSum)console.log(reducer.combineAll([Option.some(1), Option.some(2)])) // => { _id: 'Option', _tag: 'Some', value: 3 }console.log(reducer.combineAll([Option.some(1), Option.none()])) // => { _id: 'Option', _tag: 'None' }