Skip to content

Optic

Reads and updates focused parts of values without mutating the original value.

An optic describes where to look inside a value, such as a record field, a union variant, an optional value, or several values in a collection. Different optic types describe different kinds of focus: some always find a value, some may not, and some can find many. This module includes the optic types, constructors, focusing helpers, and operations for replacing, modifying, or collecting focused values.

17 exports Added in v4.0.0 Source

Constructors

entries

Added in v4.0.0 Source

Iso that converts a Record<string, A> to an array of [key, value] entries and back.

When to use

Use when you want to traverse or manipulate record entries as an array (e.g. with .forEach()).

Details

- get uses Object.entries. - set uses Object.fromEntries. - Round-trip is lossless for Record<string, A>.

See

  • Iso — the type this function returns
  • id — identity iso

Signature

declare function entries<A>(): Iso<Record<string, A>, readonly Array<readonly [string, A]>>

failure

Added in v4.0.0 Source

Prism that focuses on the failure value of a Result.

When to use

Use when you have a Result<A, E> and want to read/update E only when it is a Failure.

Details

- getResult fails when the result is a Success. - set(e) produces Result.fail(e).

See

  • success — focuses on the success side
  • Prism — the type this function returns

Signature

declare function failure<A, E>(): Prism<Result<A, E>, E>;

fromChecks

Added in v4.0.0 Source

Creates a Prism from one or more Schema validation checks.

When to use

Use when you want to narrow T to the subset that passes certain validation rules (e.g. positive integer). - You already have Schema.isGreaterThan, Schema.isInt, etc.

Details

- getResult runs all checks; fails with a combined error message when any check fails. - set is identity — the value passes through unchanged.

See

  • makePrism — constructor with custom getter/setter
  • Prism — the type this function returns

Signature

declare function fromChecks<T>(...checks: readonly [Check<T>, Check<T>]): Prism<T, T>;

id

Added in v4.0.0 Source

Iso that focuses on the whole value unchanged.

When to use

Use when you need to start an optic chain with a focus on the whole value.

Details

- get(s) returns s. - set(a) returns a. - Singleton — every call returns the same instance.

See

  • Iso — the type this function returns

Signature

declare function id<S>(): Iso<S, S>;

makeIso

Added in v4.0.0 Source

Creates an Iso from a pair of conversion functions.

When to use

Use when you have two pure conversion functions that preserve all information between S and A.

Details

The returned optic can be composed with any other optic.

See

  • Iso — the type this function returns
  • id — identity iso (no conversion)

Signature

declare function makeIso<S, A>(get: (s: S) => A, set: (a: A) => S): Iso<S, A>;

makeLens

Added in v4.0.0 Source

Creates a Lens from a getter and a replacer.

When to use

Use when you can always extract A from S and produce a new S by substituting a new A.

Details

- replace(a, s) should return a structurally new S with a in place of the old focus.

See

  • Lens — the type this function returns
  • makeIso — when no original S is needed for set

Signature

declare function makeLens<S, A>(get: (s: S) => A, replace: (a: A, s: S) => S): Lens<S, A>;

makeOptional

Added in v4.0.0 Source

Creates an Optional from a fallible getter and a fallible setter.

When to use

Use when you need an optic for a focus that may be missing on read and may reject updates on write.

Details

- getResult should return Result.fail(message) on mismatch. - set should return Result.fail(message) when the update cannot be applied.

See

  • Optional — the type this function returns
  • makeLens — when reading always succeeds
  • makePrism — when writing always succeeds

Signature

declare function makeOptional<S, A>(
  getResult: (s: S) => Result<A, string>,
  set: (a: A, s: S) => Result<S, string>,
): Optional<S, A>;

makePrism

Added in v4.0.0 Source

Creates a Prism from a fallible getter and an infallible setter.

When to use

Use when reading can fail (the part may not exist in S), but building S from A always succeeds.

Details

- getResult should return Result.fail(message) on mismatch.

See

  • Prism — the type this function returns
  • fromChecks — build from Schema checks instead

Signature

declare function makePrism<S, A>(
  getResult: (s: S) => Result<A, string>,
  set: (a: A) => S,
): Prism<S, A>;

none

Added in v4.0.0 Source

Prism that focuses on Option.None, exposing undefined.

When to use

Use when you want to match or construct None values within an optic chain.

Details

- getResult succeeds with undefined when the option is None. - getResult fails when the option is Some. - set(undefined) produces Option.none().

See

  • some — focuses on Some instead
  • Prism — the type this function returns

Signature

declare function none<A>(): Prism<Option<A>, undefined>;

some

Added in v4.0.0 Source

Prism that focuses on the value inside Option.Some.

When to use

Use when you have an Option<A> and want to read/update the inner value only when it is Some.

Details

- getResult fails with an error message when the option is None. - set(a) wraps a in Option.some(a).

See

  • none — focuses on None instead
  • Prism — the type this function returns

Signature

declare function some<A>(): Prism<Option<A>, A>;

success

Added in v4.0.0 Source

Prism that focuses on the success value of a Result.

When to use

Use when you have a Result<A, E> and want to read/update A only when it is a Success.

Details

- getResult fails when the result is a Failure. - set(a) produces Result.succeed(a).

See

  • failure — focuses on the failure side
  • Prism — the type this function returns

Signature

declare function success<A, E>(): Prism<Result<A, E>, A>;

Getters

getAll

Added in v4.0.0 Source

Returns a function that extracts all elements focused by a Traversal as a plain mutable array.

When to use

Use when you need the focused values as a simple Array<A> for further processing.

Details

- Returns an empty array when the traversal cannot focus. - Always returns a fresh array (safe to mutate).

See

  • Traversal — the optic type this operates on

Signature

declare function getAll<S, A>(traversal: Traversal<S, A>): (s: S) => Array<A>;

Models

Iso interface

Added in v4.0.0 Source

A lossless, reversible conversion between types S and A.

When to use

Use when you have a pair of functions that convert back and forth without losing information (e.g. Record ↔ entries, Celsius ↔ Fahrenheit). - You want the strongest optic that can be composed with any other.

Details

- get(s) always succeeds and returns an A. - set(a) always succeeds and returns an S. - get(set(a)) === a and set(get(s)) equals s (round-trip laws). - Extends both Lens and Prism.

See

  • makeIso — constructor
  • Lens — when you only need a one-directional focus into a whole
  • Prism — when the focus may not be present

Signature

interface Iso<in out S, in out A> extends Lens<S, A>, Prism<S, A> {}

Lens interface

Added in v4.0.0 Source

Focuses on exactly one part A inside a whole S.

When to use

Use when you always have a value to read and need the original S to produce the updated whole, unlike Iso.

Details

- get(s) always succeeds and returns A. - replace(a, s) returns a new S with the focused part replaced. - Extends Optional. - Composing a Lens with a Prism or Optional produces an Optional.

See

  • makeLens — constructor
  • Iso — when conversion is lossless in both directions
  • Optional — when reading can also fail

Signature

interface Lens<in out S, in out A> extends Optional<S, A> {
  readonly get: (s: S) => A;
}

Optional interface

Added in v4.0.0 Source

The most general optic — both reading and writing can fail.

When to use

Use when the focus may not exist in S and writing a new A back may also fail, for example when the source no longer matches the expected shape. This is the base type extended by Iso, Lens, Prism, and Traversal.

Details

- getResult(s) returns Result.Success<A> or Result.Failure<string>. - replaceResult(a, s) returns Result.Success<S> or Result.Failure<string>. - replace(a, s) returns the original s on failure (never throws). - modify(f) returns the original s on failure (never throws). - All operations are pure; inputs are never mutated.

See

Signature

interface Optional<in out S, in out A> {
  readonly getResult: (s: S) => Result<A, string>;
  readonly replace: (a: A, s: S) => S;
  readonly replaceResult: (a: A, s: S) => Result<S, string>;
  at<S, A extends object, Key extends string | number | symbol>(this: Optional<S, A>, key: Key, ..._err: ForbidUnion<A, "cannot use `at` on a union type">): Optional<S, A[Key]>;
  check<S, A>(this: Prism<S, A>, ...checks: readonly [Check<A>, Check<A>]): Prism<S, A>;
  check<S, A>(this: Optional<S, A>, ...checks: readonly [Check<A>, Check<A>]): Optional<S, A>;
  compose<B>(this: Iso<S, A>, that: Iso<A, B>): Iso<S, B>;
  compose<B>(this: Lens<S, A>, that: Lens<A, B>): Lens<S, B>;
  compose<B>(this: Prism<S, A>, that: Prism<A, B>): Prism<S, B>;
  compose<B>(this: Optional<S, A>, that: Optional<A, B>): Optional<S, B>;
  forEach<S, A, B>(this: Traversal<S, A>, f: (iso: Iso<A, A>) => Optional<A, B>): Traversal<S, B>;
  key<S, A extends object, Key extends string | number | symbol>(this: Lens<S, A>, key: Key, ..._err: ForbidUnion<A, "cannot use `key` on a union type">): Lens<S, A[Key]>;
  key<S, A extends object, Key extends string | number | symbol>(this: Optional<S, A>, key: Key, ..._err: ForbidUnion<A, "cannot use `key` on a union type">): Optional<S, A[Key]>;
  modify(f: (a: A) => A): (s: S) => S;
  modifyAll<S, A>(this: Traversal<S, A>, f: (a: A) => A): (s: S) => S;
  notUndefined<S, A>(this: Prism<S, A>): Prism<S, Exclude<A, undefined>>;
  notUndefined<S, A>(this: Optional<S, A>): Optional<S, Exclude<A, undefined>>;
  omit<S, A, Keys extends readonly Array<keyof A>>(this: Lens<S, A>, keys: Keys, ..._err: ForbidUnion<A, "cannot use `omit` on a union type">): Lens<S, Omit<A, Keys[number]>>;
  omit<S, A, Keys extends readonly Array<keyof A>>(this: Optional<S, A>, keys: Keys, ..._err: ForbidUnion<A, "cannot use `omit` on a union type">): Optional<S, Omit<A, Keys[number]>>;
  optionalKey<S, A extends object, Key extends string | number | symbol>(this: Lens<S, A>, key: Key, ..._err: ForbidUnion<A, "cannot use `optionalKey` on a union type">): Lens<S, A[Key] | undefined>;
  optionalKey<S, A extends object, Key extends string | number | symbol>(this: Optional<S, A>, key: Key, ..._err: ForbidUnion<A, "cannot use `optionalKey` on a union type">): Optional<S, A[Key] | undefined>;
  pick<S, A, Keys extends readonly Array<keyof A>>(this: Lens<S, A>, keys: Keys, ..._err: ForbidUnion<A, "cannot use `pick` on a union type">): Lens<S, Pick<A, Keys[number]>>;
  pick<S, A, Keys extends readonly Array<keyof A>>(this: Optional<S, A>, keys: Keys, ..._err: ForbidUnion<A, "cannot use `pick` on a union type">): Optional<S, Pick<A, Keys[number]>>;
  refine<S, A, B>(this: Prism<S, A>, refinement: (a: A) => a is B, annotations?: Filter): Prism<S, B>;
  refine<S, A, B>(this: Optional<S, A>, refinement: (a: A) => a is B, annotations?: Filter): Optional<S, B>;
  tag<S, A extends {
    readonly _tag: LiteralValue;
  }, Tag extends LiteralValue>(this: Prism<S, A>, tag: Tag): Prism<S, Extract<A, {
    readonly _tag: Tag;
  }>>;
  tag<S, A extends {
    readonly _tag: LiteralValue;
  }, Tag extends LiteralValue>(this: Optional<S, A>, tag: Tag): Optional<S, Extract<A, {
    readonly _tag: Tag;
  }>>;
}

Prism interface

Added in v4.0.0 Source

Focuses on a part A of S that may not be present (e.g. a union variant or a validated subset).

When to use

Use when the focus is conditional — reading can fail (wrong variant, failed validation). - Building a new S from A does not require the original S.

Details

- getResult(s) returns Result.Success<A> when the focus matches, or Result.Failure<string> with an error message. - set(a) always succeeds and returns a new S. - Extends Optional. - Composing two Prisms produces a Prism; composing a Prism with a Lens produces an Optional.

See

Signature

interface Prism<in out S, in out A> extends Optional<S, A> {
  readonly set: (a: A) => S;
}

Traversal interface

Added in v4.0.0 Source

An optic that focuses on zero or more elements of type A inside S.

When to use

Use when you want to read/update multiple elements at once (e.g. all items in an array, or a filtered subset).

Details

- Technically Optional<S, ReadonlyArray<A>> — the focused value is an array of all matched elements. - Use .forEach() to add per-element sub-optics (filtering, drilling deeper). - Use .modifyAll(f) to map a function over every focused element. - Use getAll to extract all focused elements as a plain array.

See

Signature

interface Traversal<in out S, in out A> extends Optional<S, ReadonlyArray<A>> {}