effect
Version:
The missing standard library for TypeScript, for writing production-grade software.
1,627 lines (1,591 loc) • 132 kB
text/typescript
/**
* @since 2.0.0
*/
import type { Either } from "./Either.js"
import * as Equal from "./Equal.js"
import * as Equivalence from "./Equivalence.js"
import type { LazyArg } from "./Function.js"
import { constNull, constUndefined, dual, identity, isFunction } from "./Function.js"
import type { TypeLambda } from "./HKT.js"
import type { Inspectable } from "./Inspectable.js"
import * as doNotation from "./internal/doNotation.js"
import * as either from "./internal/either.js"
import * as option from "./internal/option.js"
import type { Order } from "./Order.js"
import * as order from "./Order.js"
import type { Pipeable } from "./Pipeable.js"
import type { Predicate, Refinement } from "./Predicate.js"
import type { Covariant, NoInfer, NotFunction } from "./Types.js"
import type * as Unify from "./Unify.js"
import * as Gen from "./Utils.js"
/**
* The `Option` data type represents optional values. An `Option<A>` can either
* be `Some<A>`, containing a value of type `A`, or `None`, representing the
* absence of a value.
*
* **When to Use**
*
* You can use `Option` in scenarios like:
*
* - Using it for initial values
* - Returning values from functions that are not defined for all possible
* inputs (referred to as “partial functions”)
* - Managing optional fields in data structures
* - Handling optional function arguments
*
* @category Models
* @since 2.0.0
*/
export type Option<A> = None<A> | Some<A>
/**
* @category Symbols
* @since 2.0.0
*/
export const TypeId: unique symbol = Symbol.for("effect/Option")
/**
* @category Symbols
* @since 2.0.0
*/
export type TypeId = typeof TypeId
/**
* @category Models
* @since 2.0.0
*/
export interface None<out A> extends Pipeable, Inspectable {
readonly _tag: "None"
readonly _op: "None"
readonly [TypeId]: {
readonly _A: Covariant<A>
}
[Unify.typeSymbol]?: unknown
[Unify.unifySymbol]?: OptionUnify<this>
[Unify.ignoreSymbol]?: OptionUnifyIgnore
}
/**
* @category Models
* @since 2.0.0
*/
export interface Some<out A> extends Pipeable, Inspectable {
readonly _tag: "Some"
readonly _op: "Some"
readonly value: A
readonly [TypeId]: {
readonly _A: Covariant<A>
}
[Unify.typeSymbol]?: unknown
[Unify.unifySymbol]?: OptionUnify<this>
[Unify.ignoreSymbol]?: OptionUnifyIgnore
}
/**
* @category Models
* @since 2.0.0
*/
export interface OptionUnify<A extends { [Unify.typeSymbol]?: any }> {
Option?: () => A[Unify.typeSymbol] extends Option<infer A0> | infer _ ? Option<A0> : never
}
/**
* @since 2.0.0
*/
export declare namespace Option {
/**
* Extracts the type of the value contained in an `Option`.
*
* **Example** (Getting the Value Type of an Option)
*
* ```ts
* import { Option } from "effect"
*
* // Declare an Option holding a string
* declare const myOption: Option.Option<string>
*
* // Extract the type of the value within the Option
* //
* // ┌─── string
* // ▼
* type MyType = Option.Option.Value<typeof myOption>
* ```
*
* @since 2.0.0
* @category Type-level Utils
*/
export type Value<T extends Option<any>> = [T] extends [Option<infer _A>] ? _A : never
}
/**
* @category Models
* @since 2.0.0
*/
export interface OptionUnifyIgnore {}
/**
* @category Type Lambdas
* @since 2.0.0
*/
export interface OptionTypeLambda extends TypeLambda {
readonly type: Option<this["Target"]>
}
/**
* Represents the absence of a value by creating an empty `Option`.
*
* `Option.none` returns an `Option<never>`, which is a subtype of `Option<A>`.
* This means you can use it in place of any `Option<A>` regardless of the type
* `A`.
*
* **Example** (Creating an Option with No Value)
*
* ```ts
* import { Option } from "effect"
*
* // An Option holding no value
* //
* // ┌─── Option<never>
* // ▼
* const noValue = Option.none()
*
* console.log(noValue)
* // Output: { _id: 'Option', _tag: 'None' }
* ```
*
* @see {@link some} for the opposite operation.
*
* @category Constructors
* @since 2.0.0
*/
export const none = <A = never>(): Option<A> => option.none
/**
* Wraps the given value into an `Option` to represent its presence.
*
* **Example** (Creating an Option with a Value)
*
* ```ts
* import { Option } from "effect"
*
* // An Option holding the number 1
* //
* // ┌─── Option<number>
* // ▼
* const value = Option.some(1)
*
* console.log(value)
* // Output: { _id: 'Option', _tag: 'Some', value: 1 }
* ```
*
* @see {@link none} for the opposite operation.
*
* @category Constructors
* @since 2.0.0
*/
export const some: <A>(value: A) => Option<A> = option.some
/**
* Determines whether the given value is an `Option`.
*
* **Details**
*
* This function checks if a value is an instance of `Option`. It returns `true`
* if the value is either `Option.some` or `Option.none`, and `false` otherwise.
* This is particularly useful when working with unknown values or when you need
* to ensure type safety in your code.
*
* @example
* ```ts
* import { Option } from "effect"
*
* console.log(Option.isOption(Option.some(1)))
* // Output: true
*
* console.log(Option.isOption(Option.none()))
* // Output: true
*
* console.log(Option.isOption({}))
* // Output: false
* ```
*
* @category Guards
* @since 2.0.0
*/
export const isOption: (input: unknown) => input is Option<unknown> = option.isOption
/**
* Checks whether an `Option` represents the absence of a value (`None`).
*
* @example
* ```ts
* import { Option } from "effect"
*
* console.log(Option.isNone(Option.some(1)))
* // Output: false
*
* console.log(Option.isNone(Option.none()))
* // Output: true
* ```
*
* @see {@link isSome} for the opposite check.
*
* @category Guards
* @since 2.0.0
*/
export const isNone: <A>(self: Option<A>) => self is None<A> = option.isNone
/**
* Checks whether an `Option` contains a value (`Some`).
*
* @example
* ```ts
* import { Option } from "effect"
*
* console.log(Option.isSome(Option.some(1)))
* // Output: true
*
* console.log(Option.isSome(Option.none()))
* // Output: false
* ```
*
* @see {@link isNone} for the opposite check.
*
* @category Guards
* @since 2.0.0
*/
export const isSome: <A>(self: Option<A>) => self is Some<A> = option.isSome
/**
* Performs pattern matching on an `Option` to handle both `Some` and `None`
* cases.
*
* **Details**
*
* This function allows you to match against an `Option` and handle both
* scenarios: when the `Option` is `None` (i.e., contains no value), and when
* the `Option` is `Some` (i.e., contains a value). It executes one of the
* provided functions based on the case:
*
* - If the `Option` is `None`, the `onNone` function is executed and its result
* is returned.
* - If the `Option` is `Some`, the `onSome` function is executed with the
* contained value, and its result is returned.
*
* This function provides a concise and functional way to handle optional values
* without resorting to `if` or manual checks, making your code more declarative
* and readable.
*
* **Example** (Pattern Matching with Option)
*
* ```ts
* import { Option } from "effect"
*
* const foo = Option.some(1)
*
* const message = Option.match(foo, {
* onNone: () => "Option is empty",
* onSome: (value) => `Option has a value: ${value}`
* })
*
* console.log(message)
* // Output: "Option has a value: 1"
* ```
*
* @category Pattern matching
* @since 2.0.0
*/
export const match: {
/**
* Performs pattern matching on an `Option` to handle both `Some` and `None`
* cases.
*
* **Details**
*
* This function allows you to match against an `Option` and handle both
* scenarios: when the `Option` is `None` (i.e., contains no value), and when
* the `Option` is `Some` (i.e., contains a value). It executes one of the
* provided functions based on the case:
*
* - If the `Option` is `None`, the `onNone` function is executed and its result
* is returned.
* - If the `Option` is `Some`, the `onSome` function is executed with the
* contained value, and its result is returned.
*
* This function provides a concise and functional way to handle optional values
* without resorting to `if` or manual checks, making your code more declarative
* and readable.
*
* **Example** (Pattern Matching with Option)
*
* ```ts
* import { Option } from "effect"
*
* const foo = Option.some(1)
*
* const message = Option.match(foo, {
* onNone: () => "Option is empty",
* onSome: (value) => `Option has a value: ${value}`
* })
*
* console.log(message)
* // Output: "Option has a value: 1"
* ```
*
* @category Pattern matching
* @since 2.0.0
*/
<B, A, C = B>(
options: {
readonly onNone: LazyArg<B>
readonly onSome: (a: A) => C
}
): (self: Option<A>) => B | C
/**
* Performs pattern matching on an `Option` to handle both `Some` and `None`
* cases.
*
* **Details**
*
* This function allows you to match against an `Option` and handle both
* scenarios: when the `Option` is `None` (i.e., contains no value), and when
* the `Option` is `Some` (i.e., contains a value). It executes one of the
* provided functions based on the case:
*
* - If the `Option` is `None`, the `onNone` function is executed and its result
* is returned.
* - If the `Option` is `Some`, the `onSome` function is executed with the
* contained value, and its result is returned.
*
* This function provides a concise and functional way to handle optional values
* without resorting to `if` or manual checks, making your code more declarative
* and readable.
*
* **Example** (Pattern Matching with Option)
*
* ```ts
* import { Option } from "effect"
*
* const foo = Option.some(1)
*
* const message = Option.match(foo, {
* onNone: () => "Option is empty",
* onSome: (value) => `Option has a value: ${value}`
* })
*
* console.log(message)
* // Output: "Option has a value: 1"
* ```
*
* @category Pattern matching
* @since 2.0.0
*/
<A, B, C = B>(
self: Option<A>,
options: {
readonly onNone: LazyArg<B>
readonly onSome: (a: A) => C
}
): B | C
} = dual(
2,
<A, B, C = B>(self: Option<A>, { onNone, onSome }: {
readonly onNone: LazyArg<B>
readonly onSome: (a: A) => C
}): B | C => isNone(self) ? onNone() : onSome(self.value)
)
/**
* Converts an `Option`-returning function into a type guard.
*
* **Details**
*
* This function transforms a function that returns an `Option` into a type
* guard, ensuring type safety when validating or narrowing types. The returned
* type guard function checks whether the input satisfies the condition defined
* in the original `Option`-returning function.
*
* If the original function returns `Option.some`, the type guard evaluates to
* `true`, confirming the input is of the desired type. If the function returns
* `Option.none`, the type guard evaluates to `false`.
*
* This utility is especially useful for validating types in union types,
* filtering arrays, or ensuring safe handling of specific subtypes.
*
* @example
* ```ts
* import { Option } from "effect"
*
* type MyData = string | number
*
* const parseString = (data: MyData): Option.Option<string> =>
* typeof data === "string" ? Option.some(data) : Option.none()
*
* // ┌─── (a: MyData) => a is string
* // ▼
* const isString = Option.toRefinement(parseString)
*
* console.log(isString("a"))
* // Output: true
*
* console.log(isString(1))
* // Output: false
* ```
*
* @category Conversions
* @since 2.0.0
*/
export const toRefinement = <A, B extends A>(f: (a: A) => Option<B>): (a: A) => a is B => (a: A): a is B => isSome(f(a))
/**
* Converts an `Iterable` into an `Option`, wrapping the first element if it
* exists.
*
* **Details**
*
* This function takes an `Iterable` (e.g., an array, a generator, or any object
* implementing the `Iterable` interface) and returns an `Option` based on its
* content:
*
* - If the `Iterable` contains at least one element, the first element is
* wrapped in a `Some` and returned.
* - If the `Iterable` is empty, `None` is returned, representing the absence of
* a value.
*
* This utility is useful for safely handling collections that might be empty,
* ensuring you explicitly handle both cases where a value exists or doesn't.
*
* @example
* ```ts
* import { Option } from "effect"
*
* console.log(Option.fromIterable([1, 2, 3]))
* // Output: { _id: 'Option', _tag: 'Some', value: 1 }
*
* console.log(Option.fromIterable([]))
* // Output: { _id: 'Option', _tag: 'None' }
* ```
*
* @category Constructors
* @since 2.0.0
*/
export const fromIterable = <A>(collection: Iterable<A>): Option<A> => {
for (const a of collection) {
return some(a)
}
return none()
}
/**
* Converts an `Either` into an `Option` by discarding the error and extracting
* the right value.
*
* **Details**
*
* This function takes an `Either` and returns an `Option` based on its value:
*
* - If the `Either` is a `Right`, its value is wrapped in a `Some` and
* returned.
* - If the `Either` is a `Left`, the error is discarded, and `None` is
* returned.
*
* This is particularly useful when you only care about the success case
* (`Right`) of an `Either` and want to handle the result using `Option`. By
* using this function, you can convert `Either` into a simpler structure for
* cases where error handling is not required.
*
* @example
* ```ts
* import { Either, Option } from "effect"
*
* console.log(Option.getRight(Either.right("ok")))
* // Output: { _id: 'Option', _tag: 'Some', value: 'ok' }
*
* console.log(Option.getRight(Either.left("err")))
* // Output: { _id: 'Option', _tag: 'None' }
* ```
*
* @see {@link getLeft} for the opposite operation.
*
* @category Conversions
* @since 2.0.0
*/
export const getRight: <R, L>(self: Either<R, L>) => Option<R> = either.getRight
/**
* Converts an `Either` into an `Option` by discarding the right value and
* extracting the left value.
*
* **Details**
*
* This function transforms an `Either` into an `Option` as follows:
*
* - If the `Either` is a `Left`, its value is wrapped in a `Some` and returned.
* - If the `Either` is a `Right`, the value is discarded, and `None` is
* returned.
*
* This utility is useful when you only care about the error case (`Left`) of an
* `Either` and want to handle it as an `Option`. By discarding the right value,
* it simplifies error-focused workflows.
*
* @example
* ```ts
* import { Either, Option } from "effect"
*
* console.log(Option.getLeft(Either.right("ok")))
* // Output: { _id: 'Option', _tag: 'None' }
*
* console.log(Option.getLeft(Either.left("err")))
* // Output: { _id: 'Option', _tag: 'Some', value: 'err' }
* ```
*
* @see {@link getRight} for the opposite operation.
*
* @category Conversions
* @since 2.0.0
*/
export const getLeft: <R, L>(self: Either<R, L>) => Option<L> = either.getLeft
/**
* Returns the value contained in the `Option` if it is `Some`, otherwise
* evaluates and returns the result of `onNone`.
*
* **Details**
*
* This function allows you to provide a fallback value or computation for when
* an `Option` is `None`. If the `Option` contains a value (`Some`), that value
* is returned. If it is empty (`None`), the `onNone` function is executed, and
* its result is returned instead.
*
* This utility is helpful for safely handling `Option` values by ensuring you
* always receive a meaningful result, whether or not the `Option` contains a
* value. It is particularly useful for providing default values or alternative
* logic when working with optional values.
*
* @example
* ```ts
* import { Option } from "effect"
*
* console.log(Option.some(1).pipe(Option.getOrElse(() => 0)))
* // Output: 1
*
* console.log(Option.none().pipe(Option.getOrElse(() => 0)))
* // Output: 0
* ```
*
* @see {@link getOrNull} for a version that returns `null` instead of executing a function.
* @see {@link getOrUndefined} for a version that returns `undefined` instead of executing a function.
*
* @category Getters
* @since 2.0.0
*/
export const getOrElse: {
/**
* Returns the value contained in the `Option` if it is `Some`, otherwise
* evaluates and returns the result of `onNone`.
*
* **Details**
*
* This function allows you to provide a fallback value or computation for when
* an `Option` is `None`. If the `Option` contains a value (`Some`), that value
* is returned. If it is empty (`None`), the `onNone` function is executed, and
* its result is returned instead.
*
* This utility is helpful for safely handling `Option` values by ensuring you
* always receive a meaningful result, whether or not the `Option` contains a
* value. It is particularly useful for providing default values or alternative
* logic when working with optional values.
*
* @example
* ```ts
* import { Option } from "effect"
*
* console.log(Option.some(1).pipe(Option.getOrElse(() => 0)))
* // Output: 1
*
* console.log(Option.none().pipe(Option.getOrElse(() => 0)))
* // Output: 0
* ```
*
* @see {@link getOrNull} for a version that returns `null` instead of executing a function.
* @see {@link getOrUndefined} for a version that returns `undefined` instead of executing a function.
*
* @category Getters
* @since 2.0.0
*/
<B>(onNone: LazyArg<B>): <A>(self: Option<A>) => B | A
/**
* Returns the value contained in the `Option` if it is `Some`, otherwise
* evaluates and returns the result of `onNone`.
*
* **Details**
*
* This function allows you to provide a fallback value or computation for when
* an `Option` is `None`. If the `Option` contains a value (`Some`), that value
* is returned. If it is empty (`None`), the `onNone` function is executed, and
* its result is returned instead.
*
* This utility is helpful for safely handling `Option` values by ensuring you
* always receive a meaningful result, whether or not the `Option` contains a
* value. It is particularly useful for providing default values or alternative
* logic when working with optional values.
*
* @example
* ```ts
* import { Option } from "effect"
*
* console.log(Option.some(1).pipe(Option.getOrElse(() => 0)))
* // Output: 1
*
* console.log(Option.none().pipe(Option.getOrElse(() => 0)))
* // Output: 0
* ```
*
* @see {@link getOrNull} for a version that returns `null` instead of executing a function.
* @see {@link getOrUndefined} for a version that returns `undefined` instead of executing a function.
*
* @category Getters
* @since 2.0.0
*/
<A, B>(self: Option<A>, onNone: LazyArg<B>): A | B
} = dual(
2,
<A, B>(self: Option<A>, onNone: LazyArg<B>): A | B => isNone(self) ? onNone() : self.value
)
/**
* Returns the provided `Option` `that` if the current `Option` (`self`) is
* `None`; otherwise, it returns `self`.
*
* **Details**
*
* This function provides a fallback mechanism for `Option` values. If the
* current `Option` is `None` (i.e., it contains no value), the `that` function
* is evaluated, and its resulting `Option` is returned. If the current `Option`
* is `Some` (i.e., it contains a value), the original `Option` is returned
* unchanged.
*
* This is particularly useful for chaining fallback values or computations,
* allowing you to provide alternative `Option` values when the first one is
* empty.
*
* @example
* ```ts
* import { Option } from "effect"
*
* console.log(Option.none().pipe(Option.orElse(() => Option.none())))
* // Output: { _id: 'Option', _tag: 'None' }
*
* console.log(Option.some("a").pipe(Option.orElse(() => Option.none())))
* // Output: { _id: 'Option', _tag: 'Some', value: 'a' }
*
* console.log(Option.none().pipe(Option.orElse(() => Option.some("b"))))
* // Output: { _id: 'Option', _tag: 'Some', value: 'b' }
*
* console.log(Option.some("a").pipe(Option.orElse(() => Option.some("b"))))
* // Output: { _id: 'Option', _tag: 'Some', value: 'a' }
* ```
*
* @category Error handling
* @since 2.0.0
*/
export const orElse: {
/**
* Returns the provided `Option` `that` if the current `Option` (`self`) is
* `None`; otherwise, it returns `self`.
*
* **Details**
*
* This function provides a fallback mechanism for `Option` values. If the
* current `Option` is `None` (i.e., it contains no value), the `that` function
* is evaluated, and its resulting `Option` is returned. If the current `Option`
* is `Some` (i.e., it contains a value), the original `Option` is returned
* unchanged.
*
* This is particularly useful for chaining fallback values or computations,
* allowing you to provide alternative `Option` values when the first one is
* empty.
*
* @example
* ```ts
* import { Option } from "effect"
*
* console.log(Option.none().pipe(Option.orElse(() => Option.none())))
* // Output: { _id: 'Option', _tag: 'None' }
*
* console.log(Option.some("a").pipe(Option.orElse(() => Option.none())))
* // Output: { _id: 'Option', _tag: 'Some', value: 'a' }
*
* console.log(Option.none().pipe(Option.orElse(() => Option.some("b"))))
* // Output: { _id: 'Option', _tag: 'Some', value: 'b' }
*
* console.log(Option.some("a").pipe(Option.orElse(() => Option.some("b"))))
* // Output: { _id: 'Option', _tag: 'Some', value: 'a' }
* ```
*
* @category Error handling
* @since 2.0.0
*/
<B>(that: LazyArg<Option<B>>): <A>(self: Option<A>) => Option<B | A>
/**
* Returns the provided `Option` `that` if the current `Option` (`self`) is
* `None`; otherwise, it returns `self`.
*
* **Details**
*
* This function provides a fallback mechanism for `Option` values. If the
* current `Option` is `None` (i.e., it contains no value), the `that` function
* is evaluated, and its resulting `Option` is returned. If the current `Option`
* is `Some` (i.e., it contains a value), the original `Option` is returned
* unchanged.
*
* This is particularly useful for chaining fallback values or computations,
* allowing you to provide alternative `Option` values when the first one is
* empty.
*
* @example
* ```ts
* import { Option } from "effect"
*
* console.log(Option.none().pipe(Option.orElse(() => Option.none())))
* // Output: { _id: 'Option', _tag: 'None' }
*
* console.log(Option.some("a").pipe(Option.orElse(() => Option.none())))
* // Output: { _id: 'Option', _tag: 'Some', value: 'a' }
*
* console.log(Option.none().pipe(Option.orElse(() => Option.some("b"))))
* // Output: { _id: 'Option', _tag: 'Some', value: 'b' }
*
* console.log(Option.some("a").pipe(Option.orElse(() => Option.some("b"))))
* // Output: { _id: 'Option', _tag: 'Some', value: 'a' }
* ```
*
* @category Error handling
* @since 2.0.0
*/
<A, B>(self: Option<A>, that: LazyArg<Option<B>>): Option<A | B>
} = dual(
2,
<A, B>(self: Option<A>, that: LazyArg<Option<B>>): Option<A | B> => isNone(self) ? that() : self
)
/**
* Returns the provided default value wrapped in `Some` if the current `Option`
* (`self`) is `None`; otherwise, returns `self`.
*
* **Details**
*
* This function provides a way to supply a default value for cases where an
* `Option` is `None`. If the current `Option` is empty (`None`), the `onNone`
* function is executed to compute the default value, which is then wrapped in a
* `Some`. If the current `Option` contains a value (`Some`), it is returned as
* is.
*
* This is particularly useful for handling optional values where a fallback
* default needs to be provided explicitly in case of absence.
*
* @example
* ```ts
* import { Option } from "effect"
*
* console.log(Option.none().pipe(Option.orElseSome(() => "b")))
* // Output: { _id: 'Option', _tag: 'Some', value: 'b' }
*
* console.log(Option.some("a").pipe(Option.orElseSome(() => "b")))
* // Output: { _id: 'Option', _tag: 'Some', value: 'a' }
* ```
*
* @category Error handling
* @since 2.0.0
*/
export const orElseSome: {
/**
* Returns the provided default value wrapped in `Some` if the current `Option`
* (`self`) is `None`; otherwise, returns `self`.
*
* **Details**
*
* This function provides a way to supply a default value for cases where an
* `Option` is `None`. If the current `Option` is empty (`None`), the `onNone`
* function is executed to compute the default value, which is then wrapped in a
* `Some`. If the current `Option` contains a value (`Some`), it is returned as
* is.
*
* This is particularly useful for handling optional values where a fallback
* default needs to be provided explicitly in case of absence.
*
* @example
* ```ts
* import { Option } from "effect"
*
* console.log(Option.none().pipe(Option.orElseSome(() => "b")))
* // Output: { _id: 'Option', _tag: 'Some', value: 'b' }
*
* console.log(Option.some("a").pipe(Option.orElseSome(() => "b")))
* // Output: { _id: 'Option', _tag: 'Some', value: 'a' }
* ```
*
* @category Error handling
* @since 2.0.0
*/
<B>(onNone: LazyArg<B>): <A>(self: Option<A>) => Option<B | A>
/**
* Returns the provided default value wrapped in `Some` if the current `Option`
* (`self`) is `None`; otherwise, returns `self`.
*
* **Details**
*
* This function provides a way to supply a default value for cases where an
* `Option` is `None`. If the current `Option` is empty (`None`), the `onNone`
* function is executed to compute the default value, which is then wrapped in a
* `Some`. If the current `Option` contains a value (`Some`), it is returned as
* is.
*
* This is particularly useful for handling optional values where a fallback
* default needs to be provided explicitly in case of absence.
*
* @example
* ```ts
* import { Option } from "effect"
*
* console.log(Option.none().pipe(Option.orElseSome(() => "b")))
* // Output: { _id: 'Option', _tag: 'Some', value: 'b' }
*
* console.log(Option.some("a").pipe(Option.orElseSome(() => "b")))
* // Output: { _id: 'Option', _tag: 'Some', value: 'a' }
* ```
*
* @category Error handling
* @since 2.0.0
*/
<A, B>(self: Option<A>, onNone: LazyArg<B>): Option<A | B>
} = dual(
2,
<A, B>(self: Option<A>, onNone: LazyArg<B>): Option<A | B> => isNone(self) ? some(onNone()) : self
)
/**
* Similar to {@link orElse}, but returns an `Either` wrapped in an `Option` to
* indicate the source of the value.
*
* **Details**
*
* This function allows you to provide a fallback `Option` in case the current
* `Option` (`self`) is `None`. However, unlike `orElse`, it returns the value
* wrapped in an `Either` object, providing additional information about where
* the value came from:
*
* - If the value is from the fallback `Option` (`that`), it is wrapped in an
* `Either.right`.
* - If the value is from the original `Option` (`self`), it is wrapped in an
* `Either.left`.
*
* This is especially useful when you need to differentiate between values
* originating from the primary `Option` and those coming from the fallback,
* while still maintaining the `Option`-style handling.
*
* @category Error handling
* @since 2.0.0
*/
export const orElseEither: {
/**
* Similar to {@link orElse}, but returns an `Either` wrapped in an `Option` to
* indicate the source of the value.
*
* **Details**
*
* This function allows you to provide a fallback `Option` in case the current
* `Option` (`self`) is `None`. However, unlike `orElse`, it returns the value
* wrapped in an `Either` object, providing additional information about where
* the value came from:
*
* - If the value is from the fallback `Option` (`that`), it is wrapped in an
* `Either.right`.
* - If the value is from the original `Option` (`self`), it is wrapped in an
* `Either.left`.
*
* This is especially useful when you need to differentiate between values
* originating from the primary `Option` and those coming from the fallback,
* while still maintaining the `Option`-style handling.
*
* @category Error handling
* @since 2.0.0
*/
<B>(that: LazyArg<Option<B>>): <A>(self: Option<A>) => Option<Either<B, A>>
/**
* Similar to {@link orElse}, but returns an `Either` wrapped in an `Option` to
* indicate the source of the value.
*
* **Details**
*
* This function allows you to provide a fallback `Option` in case the current
* `Option` (`self`) is `None`. However, unlike `orElse`, it returns the value
* wrapped in an `Either` object, providing additional information about where
* the value came from:
*
* - If the value is from the fallback `Option` (`that`), it is wrapped in an
* `Either.right`.
* - If the value is from the original `Option` (`self`), it is wrapped in an
* `Either.left`.
*
* This is especially useful when you need to differentiate between values
* originating from the primary `Option` and those coming from the fallback,
* while still maintaining the `Option`-style handling.
*
* @category Error handling
* @since 2.0.0
*/
<A, B>(self: Option<A>, that: LazyArg<Option<B>>): Option<Either<B, A>>
} = dual(
2,
<A, B>(self: Option<A>, that: LazyArg<Option<B>>): Option<Either<B, A>> =>
isNone(self) ? map(that(), either.right) : map(self, either.left)
)
/**
* Returns the first `Some` value found in an `Iterable` collection of
* `Option`s, or `None` if no `Some` is found.
*
* **Details**
*
* This function iterates over a collection of `Option` values and returns the
* first `Some` it encounters. If the collection contains only `None` values,
* the result will also be `None`. This utility is useful for efficiently
* finding the first valid value in a sequence of potentially empty or invalid
* options.
*
* The iteration stops as soon as a `Some` is found, making this function
* efficient for large collections.
*
* @example
* ```ts
* import { Option } from "effect"
*
* console.log(Option.firstSomeOf([
* Option.none(),
* Option.some(1),
* Option.some(2)
* ]))
* // Output: { _id: 'Option', _tag: 'Some', value: 1 }
* ```
*
* @category Error handling
* @since 2.0.0
*/
export const firstSomeOf = <T, C extends Iterable<Option<T>> = Iterable<Option<T>>>(
collection: C
): [C] extends [Iterable<Option<infer A>>] ? Option<A> : never => {
let out: Option<unknown> = none()
for (out of collection) {
if (isSome(out)) {
return out as any
}
}
return out as any
}
/**
* Converts a nullable value into an `Option`. Returns `None` if the value is
* `null` or `undefined`, otherwise wraps the value in a `Some`.
*
* @example
* ```ts
* import { Option } from "effect"
*
* console.log(Option.fromNullable(undefined))
* // Output: { _id: 'Option', _tag: 'None' }
*
* console.log(Option.fromNullable(null))
* // Output: { _id: 'Option', _tag: 'None' }
*
* console.log(Option.fromNullable(1))
* // Output: { _id: 'Option', _tag: 'Some', value: 1 }
* ```
*
* @category Conversions
* @since 2.0.0
*/
export const fromNullable = <A>(
nullableValue: A
): Option<NonNullable<A>> => (nullableValue == null ? none() : some(nullableValue as NonNullable<A>))
/**
* Lifts a function that returns `null` or `undefined` into the `Option`
* context.
*
* **Details**
*
* This function takes a function `f` that might return `null` or `undefined`
* and transforms it into a function that returns an `Option`. The resulting
* function will return:
* - `Some` if the original function produces a non-null, non-undefined value.
* - `None` if the original function produces `null` or `undefined`.
*
* @example
* ```ts
* import { Option } from "effect"
*
* const parse = (s: string): number | undefined => {
* const n = parseFloat(s)
* return isNaN(n) ? undefined : n
* }
*
* const parseOption = Option.liftNullable(parse)
*
* console.log(parseOption("1"))
* // Output: { _id: 'Option', _tag: 'Some', value: 1 }
*
* console.log(parseOption("not a number"))
* // Output: { _id: 'Option', _tag: 'None' }
* ```
*
* @category Conversions
* @since 2.0.0
*/
export const liftNullable = <A extends ReadonlyArray<unknown>, B>(
f: (...a: A) => B | null | undefined
): (...a: A) => Option<NonNullable<B>> =>
(...a) => fromNullable(f(...a))
/**
* Returns the value contained in the `Option` if it is `Some`; otherwise,
* returns `null`.
*
* **Details**
*
* This function provides a way to extract the value of an `Option` while
* falling back to `null` if the `Option` is `None`.
*
* It is particularly useful in scenarios where `null` is an acceptable
* placeholder for the absence of a value, such as when interacting with APIs or
* systems that use `null` as a default for missing values.
*
* @example
* ```ts
* import { Option } from "effect"
*
* console.log(Option.getOrNull(Option.some(1)))
* // Output: 1
*
* console.log(Option.getOrNull(Option.none()))
* // Output: null
* ```
*
* @category Getters
* @since 2.0.0
*/
export const getOrNull: <A>(self: Option<A>) => A | null = getOrElse(constNull)
/**
* Returns the value contained in the `Option` if it is `Some`; otherwise,
* returns `undefined`.
*
* **Details**
*
* This function provides a way to extract the value of an `Option` while
* falling back to `undefined` if the `Option` is `None`.
*
* It is particularly useful in scenarios where `undefined` is an acceptable
* placeholder for the absence of a value, such as when interacting with APIs or
* systems that use `undefined` as a default for missing values.
*
* @example
* ```ts
* import { Option } from "effect"
*
* console.log(Option.getOrUndefined(Option.some(1)))
* // Output: 1
*
* console.log(Option.getOrUndefined(Option.none()))
* // Output: undefined
* ```
*
* @category Getters
* @since 2.0.0
*/
export const getOrUndefined: <A>(self: Option<A>) => A | undefined = getOrElse(constUndefined)
/**
* Lifts a function that throws exceptions into a function that returns an
* `Option`.
*
* **Details**
*
* This utility function takes a function `f` that might throw an exception and
* transforms it into a safer function that returns an `Option`. If the original
* function executes successfully, the result is wrapped in a `Some`. If an
* exception is thrown, the result is `None`, allowing the developer to handle
* errors in a functional, type-safe way.
*
* @example
* ```ts
* import { Option } from "effect"
*
* const parse = Option.liftThrowable(JSON.parse)
*
* console.log(parse("1"))
* // Output: { _id: 'Option', _tag: 'Some', value: 1 }
*
* console.log(parse(""))
* // Output: { _id: 'Option', _tag: 'None' }
* ```
*
* @category Conversions
* @since 2.0.0
*/
export const liftThrowable = <A extends ReadonlyArray<unknown>, B>(
f: (...a: A) => B
): (...a: A) => Option<B> =>
(...a) => {
try {
return some(f(...a))
} catch {
return none()
}
}
/**
* Extracts the value of an `Option` or throws an error if the `Option` is
* `None`, using a custom error factory.
*
* **Details**
*
* This function allows you to extract the value of an `Option` when it is
* `Some`. If the `Option` is `None`, it throws an error generated by the
* provided `onNone` function. This utility is particularly useful when you need
* a fail-fast behavior for empty `Option` values and want to provide a custom
* error message or object.
*
* @example
* ```ts
* import * as assert from "node:assert"
* import { Option } from "effect"
*
* assert.deepStrictEqual(
* Option.getOrThrowWith(Option.some(1), () => new Error('Unexpected None')),
* 1
* )
* assert.throws(() => Option.getOrThrowWith(Option.none(), () => new Error('Unexpected None')))
* ```
*
* @see {@link getOrThrow} for a version that throws a default error.
*
* @category Conversions
* @since 2.0.0
*/
export const getOrThrowWith: {
/**
* Extracts the value of an `Option` or throws an error if the `Option` is
* `None`, using a custom error factory.
*
* **Details**
*
* This function allows you to extract the value of an `Option` when it is
* `Some`. If the `Option` is `None`, it throws an error generated by the
* provided `onNone` function. This utility is particularly useful when you need
* a fail-fast behavior for empty `Option` values and want to provide a custom
* error message or object.
*
* @example
* ```ts
* import * as assert from "node:assert"
* import { Option } from "effect"
*
* assert.deepStrictEqual(
* Option.getOrThrowWith(Option.some(1), () => new Error('Unexpected None')),
* 1
* )
* assert.throws(() => Option.getOrThrowWith(Option.none(), () => new Error('Unexpected None')))
* ```
*
* @see {@link getOrThrow} for a version that throws a default error.
*
* @category Conversions
* @since 2.0.0
*/
(onNone: () => unknown): <A>(self: Option<A>) => A
/**
* Extracts the value of an `Option` or throws an error if the `Option` is
* `None`, using a custom error factory.
*
* **Details**
*
* This function allows you to extract the value of an `Option` when it is
* `Some`. If the `Option` is `None`, it throws an error generated by the
* provided `onNone` function. This utility is particularly useful when you need
* a fail-fast behavior for empty `Option` values and want to provide a custom
* error message or object.
*
* @example
* ```ts
* import * as assert from "node:assert"
* import { Option } from "effect"
*
* assert.deepStrictEqual(
* Option.getOrThrowWith(Option.some(1), () => new Error('Unexpected None')),
* 1
* )
* assert.throws(() => Option.getOrThrowWith(Option.none(), () => new Error('Unexpected None')))
* ```
*
* @see {@link getOrThrow} for a version that throws a default error.
*
* @category Conversions
* @since 2.0.0
*/
<A>(self: Option<A>, onNone: () => unknown): A
} = dual(2, <A>(self: Option<A>, onNone: () => unknown): A => {
if (isSome(self)) {
return self.value
}
throw onNone()
})
/**
* Extracts the value of an `Option` or throws a default error if the `Option`
* is `None`.
*
* **Details**
*
* This function extracts the value from an `Option` if it is `Some`. If the
* `Option` is `None`, it throws a default error. It is useful for fail-fast
* scenarios where the absence of a value is treated as an exceptional case and
* a default error is sufficient.
*
* @example
* ```ts
* import * as assert from "node:assert"
* import { Option } from "effect"
*
* assert.deepStrictEqual(Option.getOrThrow(Option.some(1)), 1)
* assert.throws(() => Option.getOrThrow(Option.none()))
* ```
*
* @see {@link getOrThrowWith} for a version that allows you to provide a custom error.
*
* @category Conversions
* @since 2.0.0
*/
export const getOrThrow: <A>(self: Option<A>) => A = getOrThrowWith(() => new Error("getOrThrow called on a None"))
/**
* Transforms the value inside a `Some` to a new value using the provided
* function, while leaving `None` unchanged.
*
* **Details**
*
* This function applies a mapping function `f` to the value inside an `Option`
* if it is a `Some`. If the `Option` is `None`, it remains unchanged. The
* result is a new `Option` with the transformed value (if it was a `Some`) or
* still `None`.
*
* This utility is particularly useful for chaining transformations in a
* functional way without needing to manually handle `None` cases.
*
* @example
* ```ts
* import { Option } from "effect"
*
* // Mapping over a `Some`
* const someValue = Option.some(2)
*
* console.log(Option.map(someValue, (n) => n * 2))
* // Output: { _id: 'Option', _tag: 'Some', value: 4 }
*
* // Mapping over a `None`
* const noneValue = Option.none<number>()
*
* console.log(Option.map(noneValue, (n) => n * 2))
* // Output: { _id: 'Option', _tag: 'None' }
* ```
*
* @category Mapping
* @since 2.0.0
*/
export const map: {
/**
* Transforms the value inside a `Some` to a new value using the provided
* function, while leaving `None` unchanged.
*
* **Details**
*
* This function applies a mapping function `f` to the value inside an `Option`
* if it is a `Some`. If the `Option` is `None`, it remains unchanged. The
* result is a new `Option` with the transformed value (if it was a `Some`) or
* still `None`.
*
* This utility is particularly useful for chaining transformations in a
* functional way without needing to manually handle `None` cases.
*
* @example
* ```ts
* import { Option } from "effect"
*
* // Mapping over a `Some`
* const someValue = Option.some(2)
*
* console.log(Option.map(someValue, (n) => n * 2))
* // Output: { _id: 'Option', _tag: 'Some', value: 4 }
*
* // Mapping over a `None`
* const noneValue = Option.none<number>()
*
* console.log(Option.map(noneValue, (n) => n * 2))
* // Output: { _id: 'Option', _tag: 'None' }
* ```
*
* @category Mapping
* @since 2.0.0
*/
<A, B>(f: (a: A) => B): (self: Option<A>) => Option<B>
/**
* Transforms the value inside a `Some` to a new value using the provided
* function, while leaving `None` unchanged.
*
* **Details**
*
* This function applies a mapping function `f` to the value inside an `Option`
* if it is a `Some`. If the `Option` is `None`, it remains unchanged. The
* result is a new `Option` with the transformed value (if it was a `Some`) or
* still `None`.
*
* This utility is particularly useful for chaining transformations in a
* functional way without needing to manually handle `None` cases.
*
* @example
* ```ts
* import { Option } from "effect"
*
* // Mapping over a `Some`
* const someValue = Option.some(2)
*
* console.log(Option.map(someValue, (n) => n * 2))
* // Output: { _id: 'Option', _tag: 'Some', value: 4 }
*
* // Mapping over a `None`
* const noneValue = Option.none<number>()
*
* console.log(Option.map(noneValue, (n) => n * 2))
* // Output: { _id: 'Option', _tag: 'None' }
* ```
*
* @category Mapping
* @since 2.0.0
*/
<A, B>(self: Option<A>, f: (a: A) => B): Option<B>
} = dual(
2,
<A, B>(self: Option<A>, f: (a: A) => B): Option<B> => isNone(self) ? none() : some(f(self.value))
)
/**
* Replaces the value inside a `Some` with the specified constant value, leaving
* `None` unchanged.
*
* **Details**
*
* This function transforms an `Option` by replacing the value inside a `Some`
* with the given constant value `b`. If the `Option` is `None`, it remains
* unchanged.
*
* This is useful when you want to preserve the presence of a value (`Some`) but
* replace its content with a fixed value.
*
* @example
* ```ts
* import { Option } from "effect"
*
* // Replacing the value of a `Some`
* const someValue = Option.some(42)
*
* console.log(Option.as(someValue, "new value"))
* // Output: { _id: 'Option', _tag: 'Some', value: 'new value' }
*
* // Replacing a `None` (no effect)
* const noneValue = Option.none<number>()
*
* console.log(Option.as(noneValue, "new value"))
* // Output: { _id: 'Option', _tag: 'None' }
* ```
*
* @category Mapping
* @since 2.0.0
*/
export const as: {
/**
* Replaces the value inside a `Some` with the specified constant value, leaving
* `None` unchanged.
*
* **Details**
*
* This function transforms an `Option` by replacing the value inside a `Some`
* with the given constant value `b`. If the `Option` is `None`, it remains
* unchanged.
*
* This is useful when you want to preserve the presence of a value (`Some`) but
* replace its content with a fixed value.
*
* @example
* ```ts
* import { Option } from "effect"
*
* // Replacing the value of a `Some`
* const someValue = Option.some(42)
*
* console.log(Option.as(someValue, "new value"))
* // Output: { _id: 'Option', _tag: 'Some', value: 'new value' }
*
* // Replacing a `None` (no effect)
* const noneValue = Option.none<number>()
*
* console.log(Option.as(noneValue, "new value"))
* // Output: { _id: 'Option', _tag: 'None' }
* ```
*
* @category Mapping
* @since 2.0.0
*/
<B>(b: B): <X>(self: Option<X>) => Option<B>
/**
* Replaces the value inside a `Some` with the specified constant value, leaving
* `None` unchanged.
*
* **Details**
*
* This function transforms an `Option` by replacing the value inside a `Some`
* with the given constant value `b`. If the `Option` is `None`, it remains
* unchanged.
*
* This is useful when you want to preserve the presence of a value (`Some`) but
* replace its content with a fixed value.
*
* @example
* ```ts
* import { Option } from "effect"
*
* // Replacing the value of a `Some`
* const someValue = Option.some(42)
*
* console.log(Option.as(someValue, "new value"))
* // Output: { _id: 'Option', _tag: 'Some', value: 'new value' }
*
* // Replacing a `None` (no effect)
* const noneValue = Option.none<number>()
*
* console.log(Option.as(noneValue, "new value"))
* // Output: { _id: 'Option', _tag: 'None' }
* ```
*
* @category Mapping
* @since 2.0.0
*/
<X, B>(self: Option<X>, b: B): Option<B>
} = dual(2, <X, B>(self: Option<X>, b: B): Option<B> => map(self, () => b))
/**
* Replaces the value inside a `Some` with the constant value `void`, leaving
* `None` unchanged.
*
* **Details**
*
* This function transforms an `Option` by replacing the value inside a `Some`
* with `void`. If the `Option` is `None`, it remains unchanged.
*
* This is particularly useful in scenarios where the presence or absence of a
* value is significant, but the actual content of the value is irrelevant.
*
* @category Mapping
* @since 2.0.0
*/
export const asVoid: <_>(self: Option<_>) => Option<void> = as(undefined)
const void_: Option<void> = some(undefined)
export {
/**
* @since 2.0.0
*/
void_ as void
}
/**
* Applies a function to the value of a `Some` and flattens the resulting
* `Option`. If the input is `None`, it remains `None`.
*
* **Details**
*
* This function allows you to chain computations that return `Option` values.
* If the input `Option` is `Some`, the provided function `f` is applied to the
* contained value, and the resulting `Option` is returned. If the input is
* `None`, the function is not applied, and the result remains `None`.
*
* This utility is particularly useful for sequencing operations that may fail
* or produce optional results, enabling clean and concise workflows for
* handling such cases.
*
* @example
* ```ts
* import { Option } from "effect"
*
* interface Address {
* readonly city: string
* readonly street: Option.Option<string>
* }
*
* interface User {
* readonly id: number
* readonly username: string
* readonly email: Option.Option<string>
* readonly address: Option.Option<Address>
* }
*
* const user: User = {
* id: 1,
* username: "john_doe",
* email: Option.some("john.doe@example.com"),
* address: Option.some({
* city: "New York",
* street: Option.some("123 Main St")
* })
* }
*
* // Use flatMap to extract the street value
* const street = user.address.pipe(
* Option.flatMap((address) => address.street)
* )
*
* console.log(street)
* // Output: { _id: 'Option', _tag: 'Some', value: '123 Main St' }
* ```
*
* @category Sequencing
* @since 2.0.0
*/
export const flatMap: {
/**
* Applies a function to the value of a `Some` and flattens the resulting
* `Option`. If the input is `None`, it remains `None`.
*
* **Details**
*
* This function allows you to chain computations that return `Option` values.
* If the input `Option` is `Some`, the provided function `f` is applied to the
* contained value, and the resulting `Option` is returned. If the input is
* `None`, the function is not applied, and the result remains `None`.
*
* This utility is particularly useful for sequencing operations that may fail
* or produce optional results, enabling clean and concise workflows for
* handling such cases.
*
* @example
* ```ts
* import { Option } from "effect"
*
* interface Address {
* readonly city: string
* readonly street: Option.Option<string>
* }
*
* interface User {
* readonly id: number
* readonly username: string
* readonly email: Option.Option<string>
* readonly address: Option.Option<Address>
* }
*
* const user: User = {
* id: 1,
* username: "john_doe",
* email: Option.some("john.doe@example.com"),
* address: Option.some({
* city: "New York",
* street: Option.some("123 Main St")
* })
* }
*
* // Use flatMap to extract the street value
* const street = user.address.pipe(
* Option.flatMap((address) => address.street)
* )
*
* console.log(street)
* // Output: { _id: 'Option', _tag: 'Some', value: '123 Main St' }
* ```
*
* @category Sequencing
* @since 2.0.0
*/
<A, B>(f: (a: A) => Option<B>): (self: Option<A>) => Option<B>
/**
* Applies a function to the value of a `Some` and flattens the resulting
* `Option`. If the input is `None`, it remains `None`.
*
* **Details**
*
* This function allows you to chain computations that return `Option` values.
* If the input `Option` is `Some`, the provided function `f` is applied to the
* contained value, and the resulting `Option` is