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)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"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 arrayfoo""โ real empty key
- Numeric bracket segments become array indices only when they are valid JavaScript array-index strings; otherwise they remain object keys.
- An indexed container becomes an array only when it has at most 20 holes
(missing indices below its highest index). Otherwise it is returned as an
object keyed by the index strings, so untrusted input such as
a[4294967294]cannot produce huge sparse arrays. - 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"] } }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"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")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)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")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
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])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")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])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")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])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")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")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
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")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")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")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")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")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
interfaceA 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
interfaceAn 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
interfaceA 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
interfaceAn 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"])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 at the first keyValueSeparator (default =),
preserving the rest of the value. An empty keyValueSeparator uses the first
two characters as the key and value. Pairs missing a key or value are 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
Converts a camelCase string to snake_case.
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")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")Converts a snake_case string to camelCase.
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")Converts a string to lowercase.
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")Converts a string to uppercase.
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") // => 42Creates 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)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()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")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")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
typeReplacer function or property allowlist accepted by JSON.stringify.
Signature
type JsonReplacer = (this: any, key: string, value: any) => any | Array<string | number> | nullValidation
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"