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.
Combining
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
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
- splitKeyValue for the inverse operation
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
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
Issuereturned byf. - The failure function receives the original
Option<E>input and the effectiveParseOptionsfor error context.
See
- forbidden for a convenience helper for
Forbiddenissues - 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"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"forbiddenEncoding
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"makeTreeRecord
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 arrayfoo""→ 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
- collectBracketPathEntries for flattening trees into bracket-path entries
- decodeFormData for a higher-level FormData decoder
- decodeURLSearchParams for a higher-level URLSearchParams decoder
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
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
- passthroughSupertype when
T extends E - passthroughSubtype when
E extends T - transform when you need to change the value
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 matchconst StringToString = Schema.String.pipe( Schema.decodeTo(Schema.String, { decode: SchemaGetter.passthrough(), encode: SchemaGetter.passthrough() }))Schema.decodeSync(StringToString)("hello") // => "hello"passthroughSubtype
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
- passthrough when types are identical
- passthroughSupertype when
T extends E
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 Tconst g = SchemaGetter.passthroughSubtype<string, "hello">()Effect.runSync(SchemaGetter.run(g, Option.some("hello"), {})) // => Option.some("hello")passthroughSupertype
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
- passthrough when types are identical
- passthroughSubtype when
E extends T
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 validconst g = SchemaGetter.passthroughSupertype<string, string>()Effect.runSync(SchemaGetter.run(g, Option.some("hello"), {})) // => Option.some("hello")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
- transform when you need to use the input value
- passthrough when you want to keep the input as-is
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
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)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)collectBracketPathEntries
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
FormDataorURLSearchParamsencoders.
Details
- Takes a nested object and produces flat
[bracketPath, value]pairs suitable forFormDataorURLSearchParams. - 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
- makeTreeRecord for building trees from bracket-path entries
- encodeFormData for a higher-level FormData encoder
- encodeURLSearchParams for a higher-level URLSearchParams encoder
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"]]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
- dateTimeUtcFromInput for validated DateTime parsing
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")dateTimeUtcFromInput
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
DateTimevalues, partial date/time parts, instant objects, zoned instant objects, JavaScriptDateinstances, epoch milliseconds, and date strings. - Converts successfully parsed values to UTC.
- Fails with
SchemaIssue.InvalidValueif the input cannot be parsed as a validDateTime.
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)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
- transformEffect for effectful or validated number parsing
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)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)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
- transform for custom string conversions
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
Decodes a Base64 string to a Uint8Array.
Details
- Fails with
SchemaIssue.InvalidValueif the input is not valid Base64.
See
- decodeBase64String to decode to
stringinstead - encodeBase64 for the inverse operation
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])decodeBase64String
Decodes a Base64 string to a UTF-8 string.
Details
- Fails with
SchemaIssue.InvalidValueif the input is not valid Base64.
See
- decodeBase64 to decode to
Uint8Arrayinstead - encodeBase64 for the inverse operation
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")decodeBase64Url
Decodes a URL-safe Base64 string to a Uint8Array.
Details
- Fails with
SchemaIssue.InvalidValueif the input is not valid Base64Url.
See
- decodeBase64UrlString to decode to
stringinstead - encodeBase64Url for the inverse operation
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])decodeBase64UrlString
Decodes a URL-safe Base64 string to a UTF-8 string.
Details
- Fails with
SchemaIssue.InvalidValueif the input is not valid Base64Url.
See
- decodeBase64Url to decode to
Uint8Arrayinstead - encodeBase64Url for the inverse operation
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")decodeFormData
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
- encodeFormData for the corresponding encoder
- makeTreeRecord for the underlying bracket-path parser
- decodeURLSearchParams for the URLSearchParams variant
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" } })Decodes a hexadecimal string to a Uint8Array.
Details
- Fails with
SchemaIssue.InvalidValueif the input is not valid hex.
See
- decodeHexString to decode to
stringinstead - encodeHex for the inverse operation
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])decodeHexString
Decodes a hexadecimal string to a UTF-8 string.
Details
- Fails with
SchemaIssue.InvalidValueif 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")decodeUriComponent
Decodes a URI component encoded string using decodeURIComponent.
Details
- Fails with
SchemaIssue.InvalidValueif the input contains malformed percent-encoding sequences.
See
- encodeUriComponent for the inverse operation
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")decodeURLSearchParams
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
- encodeURLSearchParams for the corresponding encoder
- makeTreeRecord for the underlying bracket-path parser
- decodeFormData for the FormData variant
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" } })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
Noneinputs. - Without
reviver: returnsSchema.MutableJson(typed JSON). - With
reviver: returnsunknown(reviver may produce arbitrary values). - On parse failure, fails with
SchemaIssue.InvalidValuewhoseexpectedannotation is"a valid JSON string". Its default message includes the reported input whenreportInputis enabled.
See
- stringifyJson for the inverse operation
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
Encodes a Uint8Array or string to a Base64 string.
Details
The getter is pure and never fails.
See
- decodeBase64 for the inverse operation to
Uint8Array - decodeBase64String for the inverse operation to
string - encodeBase64Url for the URL-safe variant
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")encodeBase64Url
Encodes a Uint8Array or string to a URL-safe Base64 string.
Details
The getter is pure and never fails.
See
- decodeBase64Url for the inverse operation to
Uint8Array - decodeBase64UrlString for the inverse operation to
string - encodeBase64 for the standard Base64 variant
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")encodeFormData
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
- decodeFormData for the corresponding decoder
- collectBracketPathEntries for the underlying flattener
- encodeURLSearchParams for the URLSearchParams variant
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")Encodes a Uint8Array or string to a hexadecimal string.
Details
The getter is pure and never fails.
See
- decodeHex for the inverse operation to
Uint8Array - decodeHexString for the inverse operation to
string
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")encodeUriComponent
Encodes a present string using encodeURIComponent.
Details
- Skips
Noneinputs. - May throw a
URIErrorfor malformed surrogate pairs; this exception is not converted into anIssue.
See
- decodeUriComponent for the inverse operation
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")encodeURLSearchParams
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
- decodeURLSearchParams for the corresponding decoder
- collectBracketPathEntries for the underlying flattener
- encodeFormData for the FormData variant
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")stringifyJson
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
Noneinputs. - If
JSON.stringifythrows or returnsundefined, fails withSchemaIssue.InvalidValue. - Supports optional
replacerandspaceoptions, matchingJSON.stringify.
See
- parseJson for the inverse operation
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
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.Noneregardless of input. - Never fails.
See
- transformOptional when you want conditional omission
- forbidden when you want to fail instead of silently omit
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
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
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
- passthrough for the identity getter
- transform to create a getter from a pure function
- transformEffect for effectful transformation
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
A transformation that returns its input unchanged.
Signature
interface Passthrough extends Pipeable { readonly _tag: "Passthrough";}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
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
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
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
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
- splitKeyValue when values are key-value pairs
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"])splitKeyValue
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
- joinKeyValue for the inverse operation
- split to split into an array of strings
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
Converts a camelCase string to snake_case.
Details
- Pure, delegates to
String.camelToSnake.
See
- snakeToCamel for the inverse operation
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
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
Converts a snake_case string to camelCase.
Details
- Pure, delegates to
String.snakeToCamel.
See
- camelToSnake for the inverse operation
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
Converts a string to lowercase.
Details
- Pure, delegates to
String.toLowerCase.
See
- toUpperCase for the inverse operation
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
Converts a string to uppercase.
Details
- Pure, delegates to
String.toUpperCase.
See
- toLowerCase for the inverse operation
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")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)toSome(f(e))and leavesNoneunchanged. - Skips
Noneinputs — only called when a value is present. - Never fails.
See
- transformEffect when the transformation returns an
Effect - transformOptional when you need to handle
Noneinputs - passthrough when no transformation is needed
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") // => 42transformEffect
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
Noneinputs — only called when a value is present. - On success, wraps the result in
Some. - On failure, propagates the
Issue.
See
- transform when transformation cannot fail
- transformOptionalEffect when you need full
Optioncontrol over the output
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)transformOptional
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
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()transformOptionalEffect
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>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
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
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)orNone, producesSome(T). - If the input is
Some(value)where value is notundefined, passes it through. defaultValueis anEffectthat will be executed each time a default is needed.
See
- transformOptionalEffect for custom effectful missing-key handling
- required when absent input should fail instead of using a default
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
Replacer function or property allowlist accepted by JSON.stringify.
Signature
type JsonReplacer = (this: any, key: string, value: any) => any | Array<string | number> | nullValidation
checkEffect
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
Some—Nonepasses through. - The check function returns a validation result:
undefinedortrue— value is valid, passes through.falseor astring— value is invalid, fails with anIssue.- An
Issueobject — fails with that issue directly. { path, issue }— fails with a nested path issue (issuemay be a message string or a full SchemaIssue.Issue).
- Does not transform the value — input and output types are the same.
See
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)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 withSchemaIssue.MissingKey. - When input is
Some, passes it through unchanged. - Optional
annotationscustomize 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"