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.
Constructors
Signature
declare function entries<A>(): Iso<Record<string, A>, readonly Array<readonly [string, A]>>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
Signature
declare function failure<A, E>(): Prism<Result<A, E>, E>;fromChecks
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
Signature
declare function fromChecks<T>(...checks: readonly [Check<T>, Check<T>]): Prism<T, T>;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>;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
Signature
declare function makeIso<S, A>(get: (s: S) => A, set: (a: A) => S): Iso<S, A>;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
Signature
declare function makeLens<S, A>(get: (s: S) => A, replace: (a: A, s: S) => S): Lens<S, A>;makeOptional
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
Signature
declare function makeOptional<S, A>(
getResult: (s: S) => Result<A, string>,
set: (a: A, s: S) => Result<S, string>,
): Optional<S, A>;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 returnsfromChecks— build fromSchemachecks instead
Signature
declare function makePrism<S, A>(
getResult: (s: S) => Result<A, string>,
set: (a: A) => S,
): Prism<S, A>;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
Signature
declare function none<A>(): Prism<Option<A>, undefined>;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
Signature
declare function some<A>(): Prism<Option<A>, A>;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
Signature
declare function success<A, E>(): Prism<Result<A, E>, A>;Getters
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
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
Signature
interface Iso<in out S, in out A> extends Lens<S, A>, Prism<S, A> {}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
Signature
interface Lens<in out S, in out A> extends Optional<S, A> {
readonly get: (s: S) => A;
}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
makeOptional— constructorLens— when reading always succeedsPrism— when writing always succeeds
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;
}>>;
}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
makePrism— constructorfromChecks— build a Prism from schema checksLens— when reading always succeeds
Signature
interface Prism<in out S, in out A> extends Optional<S, A> {
readonly set: (a: A) => S;
}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>> {}
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
-
getusesObject.entries. -setusesObject.fromEntries. - Round-trip is lossless forRecord<string, A>.See
Iso— the type this function returnsid— identity iso