Iso<S, A>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 anA.set(a)always succeeds and returns anS.get(set(a)) === aandset(get(s))equalss(round-trip laws).- Extends both Lens and Prism.
Example (Converting between Celsius and Fahrenheit)
import { Optic } from "effect"
const fahrenheit = Optic.makeIso<number, number>(
(c) => c * 9 / 5 + 32,
(f) => (f - 32) * 5 / 9
)
console.log(fahrenheit.get(100))
// Output: 212
console.log(fahrenheit.set(32))
// Output: 0export interface interface Iso<in out S, in out A>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
.
Example (Converting between Celsius and Fahrenheit)
import { Optic } from "effect"
const fahrenheit = Optic.makeIso<number, number>(
(c) => c * 9 / 5 + 32,
(f) => (f - 32) * 5 / 9
)
console.log(fahrenheit.get(100))
// Output: 212
console.log(fahrenheit.set(32))
// Output: 0
Iso<in out function (type parameter) S in Iso<in out S, in out A>S, in out function (type parameter) A in Iso<in out S, in out A>A> extends interface Lens<in out S, in out 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
.
Example (Focusing on a struct field)
import { Optic } from "effect"
type Person = { readonly name: string; readonly age: number }
const _name = Optic.id<Person>().key("name")
console.log(_name.get({ name: "Alice", age: 30 }))
// Output: "Alice"
Lens<function (type parameter) S in Iso<in out S, in out A>S, function (type parameter) A in Iso<in out S, in out A>A>, interface Prism<in out S, in out A>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
Example (Narrowing a tagged union)
import { Optic, Result } from "effect"
type Shape =
| { readonly _tag: "Circle"; readonly radius: number }
| { readonly _tag: "Rect"; readonly width: number }
const _circle = Optic.id<Shape>().tag("Circle")
console.log(Result.isSuccess(_circle.getResult({ _tag: "Circle", radius: 5 })))
// Output: true
console.log(Result.isFailure(_circle.getResult({ _tag: "Rect", width: 10 })))
// Output: true
Prism<function (type parameter) S in Iso<in out S, in out A>S, function (type parameter) A in Iso<in out S, in out A>A> {}