Skip to content
Effect Days 2026 Get your ticket

SchemaGetter

Builds one-way conversions used by schemas.

A Getter<T, E, R> receives an optional encoded value and returns an optional decoded value. It can also report a schema issue or require Effect services. Schema transformations use getters to describe one direction of a conversion, for example decoding a field from input data. This module includes basic getters, validation helpers, pure and effectful conversions, and ready-made conversions for common string, number, binary, date, form, and URL-related values.

60 exports Added in v4.0.0 Source

Combining

compose

Added in v4.0.0 Source

Composes two getters by passing the output of the first to the second.

When to use

Use when a schema conversion requires multiple transformation steps.

Details

Composition forwards Option.none() to getters that handle optional values and skips getters that operate only on present values. Composing with passthrough returns the other getter unchanged. The function supports both compose(first, second) and first.pipe(compose(second)).

Signature

declare const compose: {
<T, T2, R2>(other: Getter<T2, T, R2>): <E, R>(self: Getter<T, E, R>) => Getter<T2, E, R2 | R>;
<T, E, R, T2, R2>(self: Getter<T, E, R>, other: Getter<T2, T, R2>): Getter<T2, E, R | R2>;
}

Example

(Parsing and normalizing a number)

import { Effect, Option, SchemaGetter } from "effect"
const getter = SchemaGetter.compose(
SchemaGetter.transform<number, string>(Number),
SchemaGetter.transform((n) => Math.max(0, n))
)
Effect.runSync(SchemaGetter.run(getter, Option.some("-1"), {})) // => Option.some(0)

joinKeyValue

Added in v4.0.0 Source

Joins a record of key-value pairs into a delimited string.

When to use

Use when you need a schema getter to serialize a present decoded record as a delimited key-value string.

Details

The getter is pure and never fails. It joins entries with separator (default ,) and joins each key and value with keyValueSeparator (default =).

See

Signature

declare function joinKeyValue<E extends Record<PropertyKey, string>>(options?: {
readonly keyValueSeparator?: string;
readonly separator?: string;
}): Getter<string, E>

Example

(Joining key-value records)

import { Effect, Option, SchemaGetter } from "effect"
const join = SchemaGetter.joinKeyValue()
const result = Effect.runSync(SchemaGetter.run(join, Option.some({ a: "1", b: "2" }), {}))
result // => Option.some("a=1,b=2")

Constructors

fail

Added in v4.0.0 Source

Creates a getter that always fails with the given issue.

When to use

Use when you need a schema getter that unconditionally rejects input.

  • Building custom validation getters that produce specific error types.

Details

  • Always fails with the Issue returned by f.
  • The failure function receives the original Option<E> input and the effective ParseOptions for error context.

See

  • forbidden for a convenience helper for Forbidden issues
  • checkEffect to fail conditionally based on input value

Signature

declare function fail<T, E>(f: (oe: Option<E>, options: ParseOptions) => Issue): Getter<T, E>

Example

(Defining an always-failing getter)

import { Effect, Option, SchemaGetter, SchemaIssue } from "effect"
const rejectAll = SchemaGetter.fail<string, string>(
() => new SchemaIssue.InvalidValue({ message: "not allowed" })
)
const issue = await Effect.runPromise(
Effect.flip(SchemaGetter.run(rejectAll, Option.some("x"), {}))
)
issue._tag // => "InvalidValue"

forbidden

Added in v4.0.0 Source

Creates a getter that always fails with a Forbidden issue.

When to use

Use when you need a schema getter to disallow a field or direction (encode/decode) entirely.

  • You want a clear "forbidden" error message in schema validation output.

Details

  • Always fails with SchemaIssue.Forbidden.
  • The message function receives the Option<E> input for context.

See

  • fail to fail with a custom issue type

Signature

declare function forbidden<T, E>(message: (oe: Option<E>) => string): Getter<T, E>

Example

(Forbidding a decode direction)

import { Effect, Option, SchemaGetter } from "effect"
const noEncode = SchemaGetter.forbidden<string, number>(
() => "encoding is not supported"
)
const issue = await Effect.runPromise(
Effect.flip(SchemaGetter.run(noEncode, Option.some(1), {}))
)
issue._tag // => "Forbidden"

Getter that always fails with a Forbidden issue indicating that encoding is unsupported.

When to use

Use as the encode side of a decode-only Schema transformation.

Details

Its Getter<never, unknown> type is assignable to every encoding getter because it accepts any input and never produces an output value.

See

  • forbidden for a forbidden getter with a custom message

Signature

declare const forbiddenEncoding: Getter<never, unknown>

Example

(Rejecting encoding)

import { Effect, Option, SchemaGetter } from "effect"
const issue = await Effect.runPromise(
Effect.flip(SchemaGetter.run(SchemaGetter.forbiddenEncoding, Option.some("value"), {}))
)
issue._tag // => "Forbidden"

Builds a nested tree object from a list of bracket-path entries.

When to use

Use when you need a schema getter to parse FormData or URLSearchParams entries into structured objects.

  • You have flat key-value pairs with bracket-path keys that need nesting.

Details

  • A bracket path is a string like "user[address][city]" that describes nested object/array structure.
  • Interprets bracket paths and constructs the corresponding nested object.
  • Builds and returns a nested object from the input entries.
  • Supported syntax:
    • "foo" → object key "foo"
    • "foo[bar]" → nested { foo: { bar: ... } }
    • "foo[0]" → array index { foo: [value] }
    • "foo[]" → append to array foo
    • "" → real empty key
  • Numeric bracket segments become array indices only when they are valid JavaScript array-index strings; otherwise they remain object keys.
  • Duplicate keys for the same path are merged into arrays.
  • If a structural path conflicts with a previous leaf or a different container type, the later structural path replaces the conflicting value.
  • The notation has no escaping for ., [ or ], so keys containing these delimiters cannot be round-tripped without changing their structure.

See

Signature

declare function makeTreeRecord<A>(bracketPathEntries: readonly Array<readonly [string, A]>): TreeRecord<A>

Example

(Building a tree from bracket paths)

import { SchemaGetter } from "effect"
SchemaGetter.makeTreeRecord([
["user[name]", "Alice"],
["user[tags][]", "admin"],
["user[tags][]", "editor"]
]) // => { user: { name: "Alice", tags: ["admin", "editor"] } }

passthrough

Added in v4.0.0 Source

Returns the identity getter — passes the value through unchanged.

When to use

Use when you need a schema getter for one side of a decodeTo pair, either encode or decode, to pass values through unchanged.

Details

  • Pure, no allocation (singleton instance).
  • Optimized away by compose — composing with a passthrough is free.
  • The default overload requires T === E. Pass { strict: false } to opt out of the type constraint.

See

Signature

declare function passthrough<T, E>(options: {
readonly strict: false;
}): Getter<T, E>
declare function passthrough<T>(): Getter<T, T>

Example

(Passing through identity transformations)

import { Schema, SchemaGetter } from "effect"
// No transformation needed — types already match
const StringToString = Schema.String.pipe(
Schema.decodeTo(Schema.String, {
decode: SchemaGetter.passthrough(),
encode: SchemaGetter.passthrough()
})
)
Schema.decodeSync(StringToString)("hello") // => "hello"

Returns the identity getter, typed for when the encoded type E is a subtype of T.

When to use

Use when you need a schema getter that passes values through without { strict: false } for an encoded type that narrows the decoded type.

Details

  • Same singleton as passthrough — no allocation, optimized in composition.

See

Signature

declare function passthroughSubtype<T, E>(): Getter<T, E>

Example

(Passing through subtypes)

import { Effect, Option, SchemaGetter } from "effect"
// "hello" extends string, so E extends T
const g = SchemaGetter.passthroughSubtype<string, "hello">()
Effect.runSync(SchemaGetter.run(g, Option.some("hello"), {})) // => Option.some("hello")

Returns the identity getter typed for the relationship T extends E.

When to use

Use when you need a schema getter that passes values through when the decoded/output type is narrower than the encoded/input type.

Details

  • Same singleton as passthrough — no allocation, optimized in composition.

See

Signature

declare function passthroughSupertype<T, E>(): Getter<T, E>

Example

(Passing through supertypes)

import { Effect, Option, SchemaGetter } from "effect"
// string extends string, so this is valid
const g = SchemaGetter.passthroughSupertype<string, string>()
Effect.runSync(SchemaGetter.run(g, Option.some("hello"), {})) // => Option.some("hello")

succeed

Added in v4.0.0 Source

Creates a getter that always produces the given constant value, ignoring the input.

When to use

Use when you need a schema getter that always decodes a field to a fixed value.

Details

The getter is pure and always returns Option.some(t) regardless of whether the input is Some or None.

See

Signature

declare function succeed<T, E>(t: T): Getter<T, E>

Example

(Returning a constant getter)

import { Effect, Option, SchemaGetter } from "effect"
const alwaysZero = SchemaGetter.succeed(0)
Effect.runSync(SchemaGetter.run(alwaysZero, Option.none(), {})) // => Option.some(0)

Converting

BigInt

Added in v4.0.0 Source

Coerces a value to bigint using the global BigInt() constructor.

When to use

Use when you need a schema getter to convert a present string, number, or boolean value to bigint.

Details

  • Delegates to globalThis.BigInt.
  • Throws at runtime if the input cannot be converted (e.g. non-numeric string).

Signature

declare function BigInt<E extends string | number | bigint | boolean>(): Getter<bigint, E>

Example

(Coercing to a bigint)

import { Effect, Option, SchemaGetter } from "effect"
const toBigInt = SchemaGetter.BigInt<string>()
Effect.runSync(SchemaGetter.run(toBigInt, Option.some("42"), {})) // => Option.some(42n)

Boolean

Added in v4.0.0 Source

Coerces any value to a boolean using the global Boolean() constructor.

When to use

Use when you need a schema getter to coerce a present encoded value to a boolean with Boolean().

Details

The getter is pure, never fails, and delegates to globalThis.Boolean.

Signature

declare function Boolean<E>(): Getter<boolean, E>

Example

(Coercing to a boolean)

import { Effect, Option, SchemaGetter } from "effect"
const toBool = SchemaGetter.Boolean<string>()
Effect.runSync(SchemaGetter.run(toBool, Option.some("true"), {})) // => Option.some(true)

Flattens a nested object into bracket-path entries, filtering leaf values by a type guard.

When to use

Use when you need a schema getter to serialize structured objects to flat key-value entries.

  • Building custom FormData or URLSearchParams encoders.

Details

  • Takes a nested object and produces flat [bracketPath, value] pairs suitable for FormData or URLSearchParams.
  • Returns a curried function: first call provides the leaf type guard, second call provides the object.
  • Recursively traverses objects and arrays.
  • If all elements of an array are leaves, encodes them as multiple entries with the same key (e.g. tags=a&tags=b). Otherwise uses indexed bracket paths (e.g. items[0], items[1]).
  • Non-leaf values that aren't objects or arrays are silently skipped.
  • Empty arrays and objects produce no entries, and path delimiters in property names are not escaped. The resulting format is therefore lossy.

See

Signature

declare function collectBracketPathEntries<A>(isLeaf: (value: unknown) => value is A): (input: object) => Array<[bracketPath: string, value: A]>

Example

(Flattening an object to bracket paths)

import { Predicate, SchemaGetter } from "effect"
const collectStrings = SchemaGetter.collectBracketPathEntries(Predicate.isString)
const entries = collectStrings({ user: { name: "Alice", tags: ["admin", "editor"] } })
entries // => [["user[name]", "Alice"], ["user[tags]", "admin"], ["user[tags]", "editor"]]

Date

Added in v4.0.0 Source

Coerces a value to a Date using new Date(input).

When to use

Use when you need a schema getter to coerce a present string, number, or existing date object into a new date object.

Details

  • Delegates to new globalThis.Date(input).
  • Does not validate the result — may produce an invalid Date.

See

Signature

declare function Date<E extends string | number | Date>(): Getter<Date, E>

Example

(Coercing to a Date)

import { Effect, Option, SchemaGetter } from "effect"
const toDate = SchemaGetter.Date<string>()
const result = Effect.runSync(SchemaGetter.run(toDate, Option.some("1970-01-01"), {}))
Option.map(result, (date) => date.toISOString()) // => Option.some("1970-01-01T00:00:00.000Z")

Parses a DateTime.Input value into a DateTime.Utc.

When to use

Use when you need a schema getter to decode a present encoded date/time value to a DateTime.Utc.

Details

  • Accepted input includes existing DateTime values, partial date/time parts, instant objects, zoned instant objects, JavaScript Date instances, epoch milliseconds, and date strings.
  • Converts successfully parsed values to UTC.
  • Fails with SchemaIssue.InvalidValue if the input cannot be parsed as a valid DateTime.

See

  • Date for a simpler coercion to Date (no validation)

Signature

declare function dateTimeUtcFromInput<E extends Input>(): Getter<Utc, E>

Example

(Parsing DateTime)

import { DateTime, Effect, Option, SchemaGetter } from "effect"
const parseDate = SchemaGetter.dateTimeUtcFromInput<string>()
const result = await Effect.runPromise(
SchemaGetter.run(parseDate, Option.some("2024-01-01T00:00:00Z"), {})
)
Option.map(result, DateTime.toEpochMillis) // => Option.some(1704067200000)

Number

Added in v4.0.0 Source

Coerces any value to a number using the global Number() constructor.

When to use

Use when you need a schema getter to coerce a present encoded value to a number with Number().

Details

The getter is pure, never fails, and delegates to globalThis.Number. It may produce NaN for non-numeric inputs.

See

Signature

declare function Number<E>(): Getter<number, E>

Example

(Coercing to a number)

import { Effect, Option, SchemaGetter } from "effect"
const toNumber = SchemaGetter.Number<string>()
Effect.runSync(SchemaGetter.run(toNumber, Option.some("42"), {})) // => Option.some(42)

run

Added in v4.0.0 Source

Runs a getter directly.

Details

This is a convenience API for executing a getter outside a schema. When the getter belongs to a schema, use the corresponding SchemaParser API. The result is an Effect for every getter variant, including synchronous ones.

Signature

declare const run: {
<E>(input: Option<E>, options: ParseOptions): <T, R>(self: Getter<T, E, R>) => Effect<Option<T>, Issue, R>;
<T, E, R>(self: Getter<T, E, R>, input: Option<E>, options: ParseOptions): Effect<Option<T>, Issue, R>;
}

Example

(Running a getter)

import { Effect, Option, SchemaGetter } from "effect"
const getter = SchemaGetter.transform<number, string>(Number)
const result = Effect.runSync(
SchemaGetter.run(getter, Option.some("42"), {})
)
result // => Option.some(42)

String

Added in v4.0.0 Source

Coerces any value to a string using the global String() constructor.

When to use

Use when you need a schema getter to coerce a present encoded value to a string with String().

Details

The getter is pure, never fails, and delegates to globalThis.String.

See

Signature

declare function String<E>(): Getter<string, E>

Example

(Coercing to a string)

import { Effect, Option, SchemaGetter } from "effect"
const toString = SchemaGetter.String<number>()
Effect.runSync(SchemaGetter.run(toString, Option.some(42), {})) // => Option.some("42")

Decoding

decodeBase64

Added in v4.0.0 Source

Decodes a Base64 string to a Uint8Array.

Details

  • Fails with SchemaIssue.InvalidValue if the input is not valid Base64.

See

Signature

declare function decodeBase64<E extends string>(): Getter<Uint8Array<ArrayBufferLike>, E>

Example

(Decoding Base64 to bytes)

import { Effect, Option, SchemaGetter } from "effect"
const decode = SchemaGetter.decodeBase64<string>()
const result = await Effect.runPromise(SchemaGetter.run(decode, Option.some("AQID"), {}))
Option.map(result, Array.from) // => Option.some([1, 2, 3])

Decodes a Base64 string to a UTF-8 string.

Details

  • Fails with SchemaIssue.InvalidValue if the input is not valid Base64.

See

Signature

declare function decodeBase64String<E extends string>(): Getter<string, E>

Example

(Decoding Base64 to string)

import { Effect, Option, SchemaGetter } from "effect"
const decode = SchemaGetter.decodeBase64String<string>()
const result = await Effect.runPromise(SchemaGetter.run(decode, Option.some("aGVsbG8="), {}))
result // => Option.some("hello")

Decodes a URL-safe Base64 string to a Uint8Array.

Details

  • Fails with SchemaIssue.InvalidValue if the input is not valid Base64Url.

See

Signature

declare function decodeBase64Url<E extends string>(): Getter<Uint8Array<ArrayBufferLike>, E>

Example

(Decoding Base64Url to bytes)

import { Effect, Option, SchemaGetter } from "effect"
const decode = SchemaGetter.decodeBase64Url<string>()
const result = await Effect.runPromise(SchemaGetter.run(decode, Option.some("-_8="), {}))
Option.map(result, Array.from) // => Option.some([251, 255])

Decodes a URL-safe Base64 string to a UTF-8 string.

Details

  • Fails with SchemaIssue.InvalidValue if the input is not valid Base64Url.

See

Signature

declare function decodeBase64UrlString<E extends string>(): Getter<string, E>

Example

(Decoding Base64Url to string)

import { Effect, Option, SchemaGetter } from "effect"
const decode = SchemaGetter.decodeBase64UrlString<string>()
const result = await Effect.runPromise(SchemaGetter.run(decode, Option.some("aGVsbG8"), {}))
result // => Option.some("hello")

Decodes a FormData object into a nested tree structure using bracket-path notation.

When to use

Use when you need a schema getter to parse FormData from HTTP requests into structured objects.

Details

The getter is pure and never fails. It interprets bracket-path keys such as user[name] and items[0] to build nested objects or arrays, and each leaf value is a string or Blob.

See

Signature

declare function decodeFormData(): Getter<TreeRecord<string | Blob>, FormData>

Example

(Decoding FormData)

import { Effect, Option, SchemaGetter } from "effect"
const decode = SchemaGetter.decodeFormData()
const formData = new FormData()
formData.append("user[name]", "Alice")
const result = Effect.runSync(SchemaGetter.run(decode, Option.some(formData), {}))
result // => Option.some({ user: { name: "Alice" } })

decodeHex

Added in v4.0.0 Source

Decodes a hexadecimal string to a Uint8Array.

Details

  • Fails with SchemaIssue.InvalidValue if the input is not valid hex.

See

Signature

declare function decodeHex<E extends string>(): Getter<Uint8Array<ArrayBufferLike>, E>

Example

(Decoding hex to bytes)

import { Effect, Option, SchemaGetter } from "effect"
const decode = SchemaGetter.decodeHex<string>()
const result = await Effect.runPromise(SchemaGetter.run(decode, Option.some("010203"), {}))
Option.map(result, Array.from) // => Option.some([1, 2, 3])

Decodes a hexadecimal string to a UTF-8 string.

Details

  • Fails with SchemaIssue.InvalidValue if the input is not valid hex.

See

Signature

declare function decodeHexString<E extends string>(): Getter<string, E>

Example

(Decoding hex to string)

import { Effect, Option, SchemaGetter } from "effect"
const decode = SchemaGetter.decodeHexString<string>()
const result = await Effect.runPromise(SchemaGetter.run(decode, Option.some("68656c6c6f"), {}))
result // => Option.some("hello")

Decodes a URI component encoded string using decodeURIComponent.

Details

  • Fails with SchemaIssue.InvalidValue if the input contains malformed percent-encoding sequences.

See

Signature

declare function decodeUriComponent<E extends string>(): Getter<string, E>

Example

(Decoding a URI component)

import { Effect, Option, SchemaGetter } from "effect"
const decode = SchemaGetter.decodeUriComponent<string>()
const result = await Effect.runPromise(SchemaGetter.run(decode, Option.some("hello%20world"), {}))
result // => Option.some("hello world")

Decodes a URLSearchParams object into a nested tree structure using bracket-path notation.

When to use

Use when you need a schema getter to parse query parameters from URLs into structured objects.

Details

The getter is pure and never fails. It interprets bracket-path keys such as user[name] and items[0] to build nested objects or arrays, and each leaf value is a string.

See

Signature

declare function decodeURLSearchParams(): Getter<TreeRecord<string>, URLSearchParams>

Example

(Decoding URLSearchParams)

import { Effect, Option, SchemaGetter } from "effect"
const decode = SchemaGetter.decodeURLSearchParams()
const params = new URLSearchParams("user[name]=Alice")
const result = Effect.runSync(SchemaGetter.run(decode, Option.some(params), {}))
result // => Option.some({ user: { name: "Alice" } })

parseJson

Added in v4.0.0 Source

Parses a JSON string into a value.

When to use

Use when you need a schema getter to parse a present encoded JSON string during decoding.

Details

  • Skips None inputs.
  • Without reviver: returns Schema.MutableJson (typed JSON).
  • With reviver: returns unknown (reviver may produce arbitrary values).
  • On parse failure, fails with SchemaIssue.InvalidValue whose expected annotation is "a valid JSON string". Its default message includes the reported input when reportInput is enabled.

See

Signature

declare function parseJson<E extends string>(): Getter<MutableJson, E>
declare function parseJson<E extends string>(options: ParseJsonOptions): Getter<unknown, E>

Example

(Parsing JSON)

import { Effect, Option, SchemaGetter } from "effect"
const parse = SchemaGetter.parseJson<string>()
const result = await Effect.runPromise(SchemaGetter.run(parse, Option.some("{\"a\":1}"), {}))
result // => Option.some({ a: 1 })

Encoding

encodeBase64

Added in v4.0.0 Source

Encodes a Uint8Array or string to a Base64 string.

Details

The getter is pure and never fails.

See

Signature

declare function encodeBase64<E extends string | Uint8Array<ArrayBufferLike>>(): Getter<string, E>

Example

(Encoding to Base64)

import { Effect, Option, SchemaGetter } from "effect"
const encode = SchemaGetter.encodeBase64<Uint8Array>()
const result = Effect.runSync(SchemaGetter.run(encode, Option.some(new Uint8Array([1, 2, 3])), {}))
result // => Option.some("AQID")

Encodes a Uint8Array or string to a URL-safe Base64 string.

Details

The getter is pure and never fails.

See

Signature

declare function encodeBase64Url<E extends string | Uint8Array<ArrayBufferLike>>(): Getter<string, E>

Example

(Encoding to Base64Url)

import { Effect, Option, SchemaGetter } from "effect"
const encode = SchemaGetter.encodeBase64Url<Uint8Array>()
const result = Effect.runSync(SchemaGetter.run(encode, Option.some(new Uint8Array([251, 255])), {}))
result // => Option.some("-_8")

Encodes a nested object into a FormData instance using bracket-path notation.

When to use

Use when you need a schema getter to serialize structured data to FormData for HTTP requests.

Details

The getter is pure and never fails. It flattens nested objects or arrays into bracket-path keys such as user[name] and items[0]. Non-object inputs produce an empty FormData.

See

Signature

declare function encodeFormData(): Getter<FormData, unknown>

Example

(Encoding to FormData)

import { Effect, Option, SchemaGetter } from "effect"
const encode = SchemaGetter.encodeFormData()
const result = Effect.runSync(SchemaGetter.run(encode, Option.some({ name: "Alice" }), {}))
Option.map(result, (formData) => formData.get("name")) // => Option.some("Alice")

encodeHex

Added in v4.0.0 Source

Encodes a Uint8Array or string to a hexadecimal string.

Details

The getter is pure and never fails.

See

Signature

declare function encodeHex<E extends string | Uint8Array<ArrayBufferLike>>(): Getter<string, E>

Example

(Encoding to hex)

import { Effect, Option, SchemaGetter } from "effect"
const encode = SchemaGetter.encodeHex<Uint8Array>()
const result = Effect.runSync(SchemaGetter.run(encode, Option.some(new Uint8Array([1, 2, 3])), {}))
result // => Option.some("010203")

Encodes a present string using encodeURIComponent.

Details

  • Skips None inputs.
  • May throw a URIError for malformed surrogate pairs; this exception is not converted into an Issue.

See

Signature

declare function encodeUriComponent<E extends string>(): Getter<string, E>

Example

(Encoding a URI component)

import { Effect, Option, SchemaGetter } from "effect"
const encode = SchemaGetter.encodeUriComponent<string>()
const result = Effect.runSync(SchemaGetter.run(encode, Option.some("hello world"), {}))
result // => Option.some("hello%20world")

Encodes a nested object into a URLSearchParams instance using bracket-path notation.

When to use

Use when you need a schema getter to serialize structured data to query parameters for URLs.

Details

The getter is pure and never fails. It flattens nested objects or arrays into bracket-path keys. Non-object inputs produce an empty URLSearchParams.

See

Signature

declare function encodeURLSearchParams(): Getter<URLSearchParams, unknown>

Example

(Encoding to URLSearchParams)

import { Effect, Option, SchemaGetter } from "effect"
const encode = SchemaGetter.encodeURLSearchParams()
const result = Effect.runSync(SchemaGetter.run(encode, Option.some({ name: "Alice" }), {}))
Option.map(result, (params) => params.toString()) // => Option.some("name=Alice")

Stringifies a present value using JSON.stringify.

When to use

Use when you need a schema getter to serialize a present decoded value to JSON text during encoding.

Details

  • Skips None inputs.
  • If JSON.stringify throws or returns undefined, fails with SchemaIssue.InvalidValue.
  • Supports optional replacer and space options, matching JSON.stringify.

See

Signature

declare function stringifyJson(options?: StringifyJsonOptions): Getter<string, unknown>

Example

(Stringifying JSON)

import { Effect, Option, SchemaGetter } from "effect"
const stringify = SchemaGetter.stringifyJson()
const result = await Effect.runPromise(SchemaGetter.run(stringify, Option.some({ a: 1 }), {}))
result // => Option.some("{\"a\":1}")

Filtering

omit

Added in v4.0.0 Source

Creates a getter that always returns None, effectively omitting the value from output.

When to use

Use when you need a schema getter to exclude a field during decoding or encoding.

Details

  • Always returns Option.None regardless of input.
  • Never fails.

See

Signature

declare function omit<T>(): Getter<never, T>

Example

(Omitting a field during encoding)

import { Effect, Option, SchemaGetter } from "effect"
const omitField = SchemaGetter.omit<string>()
Effect.runSync(SchemaGetter.run(omitField, Option.some("hidden"), {})) // => Option.none()

Mapping

map

Added in v4.0.0 Source

Maps the output of a getter while preserving missing values.

When to use

Use to add a synchronous transformation after an existing getter.

Details

The mapping function runs only for Option.some. The function supports both map(self, f) and self.pipe(map(f)).

Signature

declare const map: {
<T, T2>(f: (value: T) => T2): <E, R>(self: Getter<T, E, R>) => Getter<T2, E, R>;
<T, E, R, T2>(self: Getter<T, E, R>, f: (value: T) => T2): Getter<T2, E, R>;
}

Example

(Mapping a getter result)

import { Effect, Option, SchemaGetter } from "effect"
const getter = SchemaGetter.transform<number, string>(Number).pipe(
SchemaGetter.map((n) => n * 2)
)
Effect.runSync(SchemaGetter.run(getter, Option.some("21"), {})) // => Option.some(42)

Models

Getter type

Added in v4.0.0 Source

Represents a composable transformation from an encoded type E to a decoded type T.

When to use

Use when you need a schema getter to build and compose custom transformations for Schema.decodeTo or Schema.decode.

Details

A getter receives an Option<E> and produces an Option<T>. Option.none() represents a missing struct field and can also omit a field from the output. A getter may fail with a schema issue or require services through R. The tagged representation distinguishes synchronous transformations from transformations that return an Effect, allowing schema parsers to select the corresponding execution path when they are built. Getter values expose pipe; use the standalone map, compose, and run functions to operate on them.

See

Signature

type Getter<T, E, R = never> = Passthrough | Transform<T, E> | TransformOptional<T, E> | TransformEffect<T, E, R> | TransformOptionalEffect<T, E, R>

Example

(Creating and composing getters)

import { Effect, Option, SchemaGetter } from "effect"
const parseNumber = SchemaGetter.transform<number, string>((s) => Number(s))
const double = SchemaGetter.transform<number, number>((n) => n * 2)
const composed = SchemaGetter.compose(parseNumber, double)
Effect.runSync(SchemaGetter.run(composed, Option.some("21"), {})) // => Option.some(42)

Passthrough interface

Added in v4.0.0 Source

A transformation that returns its input unchanged.

Signature

interface Passthrough extends Pipeable {
readonly _tag: "Passthrough";
}

Transform interface

Added in v4.0.0 Source

A synchronous transformation of present values.

Signature

interface Transform<out T, in E> extends Pipeable {
readonly _tag: "Transform";
readonly transform: (input: E) => T;
}

TransformEffect interface

Added in v4.0.0 Source

An effectful transformation of present values.

Signature

interface TransformEffect<out T, in E, R> extends Pipeable {
readonly _tag: "TransformEffect";
readonly transform: (input: E, options: ParseOptions) => Effect<T, Issue, R>;
}

TransformOptional interface

Added in v4.0.0 Source

A synchronous transformation of optional values.

Signature

interface TransformOptional<out T, in E> extends Pipeable {
readonly _tag: "TransformOptional";
readonly transform: (input: Option<E>) => Option<T>;
}

TransformOptionalEffect interface

Added in v4.0.0 Source

An effectful transformation of optional values.

Signature

interface TransformOptionalEffect<out T, in E, R> extends Pipeable {
readonly _tag: "TransformOptionalEffect";
readonly transform: (input: Option<E>, options: ParseOptions) => Effect<Option<T>, Issue, R>;
}

Splitting

split

Added in v4.0.0 Source

Splits a string into an array of strings by a separator.

When to use

Use when you need a schema getter to split a present encoded string containing a delimited list, such as CSV values.

Details

The getter is pure and never fails. It splits by separator (default ,). An empty string produces an empty array, not [""].

See

Signature

declare function split<E extends string>(options?: {
readonly separator?: string;
}): Getter<readonly Array<string>, E>

Example

(Splitting a comma-separated string)

import { Effect, Option, SchemaGetter } from "effect"
const splitComma = SchemaGetter.split<string>()
const result = Effect.runSync(SchemaGetter.run(splitComma, Option.some("a,b,c"), {}))
result // => Option.some(["a", "b", "c"])

Parses a string into a record of key-value pairs.

When to use

Use when you need a schema getter to parse a present encoded string that contains delimited key-value pairs (e.g. "a=1,b=2").

Details

The getter is pure and never fails. It splits the string by separator (default ,) and then each pair by keyValueSeparator (default =). Pairs missing a key or value are silently skipped.

See

Signature

declare function splitKeyValue<E extends string>(options?: {
readonly keyValueSeparator?: string;
readonly separator?: string;
}): Getter<Record<string, string>, E>

Example

(Parsing a key-value string)

import { Effect, Option, SchemaGetter } from "effect"
const parse = SchemaGetter.splitKeyValue<string>()
const result = Effect.runSync(SchemaGetter.run(parse, Option.some("a=1,b=2"), {}))
result // => Option.some({ a: "1", b: "2" })

Transforming

camelToSnake

Added in v4.0.0 Source

Converts a camelCase string to snake_case.

Details

  • Pure, delegates to String.camelToSnake.

See

Signature

declare function camelToSnake<E extends string>(): Getter<string, E>

Example

(Converting camel case to snake case)

import { Effect, Option, SchemaGetter } from "effect"
const toSnake = SchemaGetter.camelToSnake<string>()
Effect.runSync(SchemaGetter.run(toSnake, Option.some("userName"), {})) // => Option.some("user_name")

capitalize

Added in v4.0.0 Source

Capitalizes the first character of a string.

Details

  • Pure, delegates to String.capitalize.

Signature

declare function capitalize<E extends string>(): Getter<string, E>

Example

(Capitalizing a string)

import { Effect, Option, SchemaGetter } from "effect"
const cap = SchemaGetter.capitalize<string>()
Effect.runSync(SchemaGetter.run(cap, Option.some("hello"), {})) // => Option.some("Hello")

snakeToCamel

Added in v4.0.0 Source

Converts a snake_case string to camelCase.

Details

  • Pure, delegates to String.snakeToCamel.

See

Signature

declare function snakeToCamel<E extends string>(): Getter<string, E>

Example

(Converting snake case to camel case)

import { Effect, Option, SchemaGetter } from "effect"
const toCamel = SchemaGetter.snakeToCamel<string>()
Effect.runSync(SchemaGetter.run(toCamel, Option.some("user_name"), {})) // => Option.some("userName")

toLowerCase

Added in v4.0.0 Source

Converts a string to lowercase.

Details

  • Pure, delegates to String.toLowerCase.

See

Signature

declare function toLowerCase<E extends string>(): Getter<string, E>

Example

(Converting to lowercase)

import { Effect, Option, SchemaGetter } from "effect"
const lower = SchemaGetter.toLowerCase<string>()
Effect.runSync(SchemaGetter.run(lower, Option.some("HELLO"), {})) // => Option.some("hello")

toUpperCase

Added in v4.0.0 Source

Converts a string to uppercase.

Details

  • Pure, delegates to String.toUpperCase.

See

Signature

declare function toUpperCase<E extends string>(): Getter<string, E>

Example

(Converting to uppercase)

import { Effect, Option, SchemaGetter } from "effect"
const upper = SchemaGetter.toUpperCase<string>()
Effect.runSync(SchemaGetter.run(upper, Option.some("hello"), {})) // => Option.some("HELLO")

transform

Added in v4.0.0 Source

Creates a getter that applies a pure function to present values.

When to use

Use when you need a schema getter for a pure, infallible transformation between types.

  • Building encode/decode pairs for Schema.decodeTo.

Details

  • This is the most commonly used constructor.
  • Transforms Some(e) to Some(f(e)) and leaves None unchanged.
  • Skips None inputs — only called when a value is present.
  • Never fails.

See

Signature

declare function transform<T, E>(f: (e: E) => T): Getter<T, E>

Example

(Transforming strings to numbers)

import { Schema, SchemaGetter } from "effect"
const NumberFromString = Schema.String.pipe(
Schema.decodeTo(Schema.Number, {
decode: SchemaGetter.transform((s) => Number(s)),
encode: SchemaGetter.transform((n) => String(n))
})
)
Schema.decodeSync(NumberFromString)("42") // => 42

Creates a getter that applies an effectful transformation to present values.

When to use

Use when you need a schema getter for a transformation that may fail, require Effect services, or run asynchronously.

Details

  • Skips None inputs — only called when a value is present.
  • On success, wraps the result in Some.
  • On failure, propagates the Issue.

See

Signature

declare function transformEffect<T, E, R = never>(f: (e: E, options: ParseOptions) => Effect<T, Issue, R>): Getter<T, E, R>

Example

(Parsing with failure)

import { Effect, Option, SchemaGetter, SchemaIssue } from "effect"
const safeParseInt = SchemaGetter.transformEffect<number, string>(
(s, options) => {
const n = parseInt(s, 10)
return isNaN(n)
? Effect.fail(new SchemaIssue.InvalidValue({ message: "not an integer" }, s, options))
: Effect.succeed(n)
}
)
await Effect.runPromise(SchemaGetter.run(safeParseInt, Option.some("42"), {})) // => Option.some(42)

Creates a getter that transforms the full Option — both present and absent values.

When to use

Use when you need a schema getter to handle both Some and None cases.

Details

The getter is pure and never fails. It receives the full Option<E> and must return Option<T>, so it can turn a present value into absent or an absent value into present.

See

  • transform when you only need to transform present values
  • omit when you always want None

Signature

declare function transformOptional<T, E>(f: (oe: Option<E>) => Option<T>): Getter<T, E>

Example

(Filtering out empty strings)

import { Effect, Option, SchemaGetter } from "effect"
const skipEmpty = SchemaGetter.transformOptional<string, string>((o) =>
Option.filter(o, (s) => s.length > 0)
)
Effect.runSync(SchemaGetter.run(skipEmpty, Option.some(""), {})) // => Option.none()

Creates a getter that effectfully transforms the full Option.

Signature

declare function transformOptionalEffect<T, E, R = never>(f: (input: Option<E>, options: ParseOptions) => Effect<Option<T>, Issue, R>): Getter<T, E, R>

trim

Added in v4.0.0 Source

Strips whitespace from both ends of a string.

Details

  • Pure, delegates to String.trim.

Signature

declare function trim<E extends string>(): Getter<string, E>

Example

(Trimming whitespace)

import { Effect, Option, SchemaGetter } from "effect"
const trimmed = SchemaGetter.trim<string>()
Effect.runSync(SchemaGetter.run(trimmed, Option.some(" hello "), {})) // => Option.some("hello")

uncapitalize

Added in v4.0.0 Source

Uncapitalizes the first character of a string.

Details

  • Pure, delegates to String.uncapitalize.

Signature

declare function uncapitalize<E extends string>(): Getter<string, E>

Example

(Uncapitalizing a string)

import { Effect, Option, SchemaGetter } from "effect"
const uncap = SchemaGetter.uncapitalize<string>()
Effect.runSync(SchemaGetter.run(uncap, Option.some("Hello"), {})) // => Option.some("hello")

withDefault

Added in v4.0.0 Source

Creates a getter that replaces undefined values with a default.

When to use

Use when you need a schema getter to provide a fallback for a field that may be undefined in the encoded input.

Details

  • If the input is Some(undefined) or None, produces Some(T).
  • If the input is Some(value) where value is not undefined, passes it through.
  • defaultValue is an Effect that will be executed each time a default is needed.

See

Signature

declare function withDefault<T, R = never>(defaultValue: Effect<T, Issue, R>): Getter<T, T | undefined, R>

Example

(Providing a default value for an optional field)

import { Effect, Option, SchemaGetter } from "effect"
const withZero = SchemaGetter.withDefault(Effect.succeed(0))
await Effect.runPromise(SchemaGetter.run(withZero, Option.some(undefined), {})) // => Option.some(0)

Utility Types

JsonReplacer type

Added in v4.0.0 Source

Replacer function or property allowlist accepted by JSON.stringify.

Signature

type JsonReplacer = (this: any, key: string, value: any) => any | Array<string | number> | null

Validation

checkEffect

Added in v4.0.0 Source

Creates a getter that validates a value using an effectful check function.

When to use

Use when you need a schema getter to validate a decoded value (e.g. check a constraint or call an external service).

  • The validation may be asynchronous or require Effect services.

Details

  • Only runs when input is SomeNone passes through.
  • The check function returns a validation result:
    • undefined or true — value is valid, passes through.
    • false or a string — value is invalid, fails with an Issue.
    • An Issue object — fails with that issue directly.
    • { path, issue } — fails with a nested path issue (issue may be a message string or a full SchemaIssue.Issue).
  • Does not transform the value — input and output types are the same.

See

  • transform when you need to change the value, not just validate
  • fail for unconditional failure

Signature

declare function checkEffect<T, R = never>(f: (input: T, options: ParseOptions) => Effect<boolean | FilterIssue | undefined, never, R>): Getter<T, T, R>

Example

(Validating effectfully)

import { Effect, Option, SchemaGetter } from "effect"
const nonNegative = SchemaGetter.checkEffect<number>((n) =>
Effect.succeed(n >= 0 ? undefined : "must be non-negative")
)
await Effect.runPromise(SchemaGetter.run(nonNegative, Option.some(1), {})) // => Option.some(1)

required

Added in v4.0.0 Source

Creates a getter that fails with MissingKey if the input is absent (Option.None).

When to use

Use when you need a schema getter to require a struct field in the encoded input and report a missing key error when it is absent.

Details

  • When input is None, fails with SchemaIssue.MissingKey.
  • When input is Some, passes it through unchanged.
  • Optional annotations customize the error message for the missing key.

See

  • withDefault to substitute a default for undefined values

Signature

declare function required<T, E = T>(annotations?: Key<T>): Getter<T, E>

Example

(Defining a required struct field)

import { Effect, Option, SchemaGetter } from "effect"
const mustExist = SchemaGetter.required<string>()
const issue = await Effect.runPromise(
Effect.flip(SchemaGetter.run(mustExist, Option.none(), {}))
)
issue._tag // => "MissingKey"