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
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()await Effect.runPromise(join.run(Option.some({ a: "1", b: "2" }), {})) // => 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(rejectAll.run(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(noEncode.run(Option.some(1), {})))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
- 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 during
.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">()await Effect.runPromise(g.run(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>()await Effect.runPromise(g.run(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)await Effect.runPromise(alwaysZero.run(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>()await Effect.runPromise(toBigInt.run(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>()await Effect.runPromise(toBool.run(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 = await Effect.runPromise(toDate.run(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(parseDate.run(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
- transformOrFail for 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>()await Effect.runPromise(toNumber.run(Option.some("42"), {})) // => 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>()await Effect.runPromise(toString.run(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(decode.run(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>()await Effect.runPromise(decode.run(Option.some("aGVsbG8="), {})) // => 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(decode.run(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>()await Effect.runPromise(decode.run(Option.some("aGVsbG8"), {})) // => 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")await Effect.runPromise(decode.run(Option.some(formData), {})) // => 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(decode.run(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>()await Effect.runPromise(decode.run(Option.some("68656c6c6f"), {})) // => 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>()await Effect.runPromise(decode.run(Option.some("hello%20world"), {})) // => 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")await Effect.runPromise(decode.run(Option.some(params), {})) // => 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>()await Effect.runPromise(parse.run(Option.some("{\"a\":1}"), {})) // => 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>()await Effect.runPromise(encode.run(Option.some(new Uint8Array([1, 2, 3])), {})) // => 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>()await Effect.runPromise(encode.run(Option.some(new Uint8Array([251, 255])), {})) // => 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 = await Effect.runPromise(encode.run(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>()await Effect.runPromise(encode.run(Option.some(new Uint8Array([1, 2, 3])), {})) // => 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>()await Effect.runPromise(encode.run(Option.some("hello world"), {})) // => 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 = await Effect.runPromise(encode.run(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()await Effect.runPromise(stringify.run(Option.some({ a: 1 }), {})) // => 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>()await Effect.runPromise(omitField.run(Option.some("hidden"), {})) // => Option.none()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 wraps a function Option<E> -> Effect<Option<T>, Issue, R>. It
receives Option.None when the encoded key is absent, such as a missing
struct field, and returns Option.None to omit the value from the decoded
output. It fails with Issue on invalid input and may require Effect
services via R. .map(f) applies f to the decoded value inside Some
while leaving None unchanged. .compose(other) chains two getters by
feeding the output of this into other; passthrough getters on either side
are optimized away.
See
- transform to create a getter from a pure function
- passthrough for the identity getter
- transformOrFail for fallible transformation
Signature
declare class Getter<out T, in E, R = never> extends Class { constructor<out T, in E, R = never>(run: (input: Option<E>, options: ParseOptions) => Effect<Option<T>, Issue, R>); readonly run: (input: Option<E>, options: ParseOptions) => Effect<Option<T>, Issue, R>; compose<T2, R2>(other: Getter<T2, T, R2>): Getter<T2, E, R | R2>; map<T2>(f: (t: T) => T2): Getter<T2, 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 = parseNumber.compose(double)await Effect.runPromise(composed.run(Option.some("21"), {})) // => Option.some(42)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>()await Effect.runPromise(splitComma.run(Option.some("a,b,c"), {})) // => 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>()await Effect.runPromise(parse.run(Option.some("a=1,b=2"), {})) // => 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>()await Effect.runPromise(toSnake.run(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>()await Effect.runPromise(cap.run(Option.some("hello"), {})) // => Option.some("Hello")Creates a getter that handles the case when the input is absent (Option.None).
When to use
Use when you need a schema getter to provide a fallback or computed value for missing struct keys.
- Building custom "default value" logic more complex than withDefault.
Details
- When input is
None, callsfto produce the result. - When input is
Some, passes it through unchanged. freceives the parse options and may returnNoneto keep the value absent.
See
- required when absent input should fail
- withDefault for a simpler default value for undefined inputs
- onSome to handle only present values
Signature
declare function onNone<T, E = T, R = never>(f: (options: ParseOptions) => Effect<Option<T>, Issue, R>): Getter<T, E, R>Example
(Providing a default timestamp for a missing field)
import { Effect, Option, SchemaGetter } from "effect"
const withTimestamp = SchemaGetter.onNone<number>(() => Effect.succeed(Option.some(0)))await Effect.runPromise(withTimestamp.run(Option.none(), {})) // => Option.some(0)Creates a getter that handles present values (Option.Some), passing None through.
When to use
Use when you need a schema getter to transform or validate only when a field value is present.
- Missing keys should remain absent in the output.
Details
- When input is
None, returnsNone(no-op). - When input is
Some(e), callsf(e, options)to produce the result. fmay returnNoneto omit the value, or fail with anIssue.
See
- onNone to handle only absent values
- transform for a simpler pure transformation of present values
- transformOrFail for fallible transformation of present values
Signature
declare function onSome<T, E, R = never>(f: (e: E, options: ParseOptions) => Effect<Option<T>, Issue, R>): Getter<T, E, R>Example
(Transforming only present values)
import { Effect, Option, SchemaGetter } from "effect"
const parseIfPresent = SchemaGetter.onSome<number, string>( (s) => Effect.succeed(Option.some(Number(s))))await Effect.runPromise(parseIfPresent.run(Option.some("42"), {})) // => Option.some(42)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>()await Effect.runPromise(toCamel.run(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>()await Effect.runPromise(lower.run(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>()await Effect.runPromise(upper.run(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
- transformOrFail when the transformation can fail
- 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") // => 42transformOptional
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))await Effect.runPromise(skipEmpty.run(Option.some(""), {})) // => Option.none()transformOrFail
Creates a getter that applies a fallible, 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
Signature
declare function transformOrFail<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.transformOrFail<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(safeParseInt.run(Option.some("42"), {})) // => Option.some(42)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>()await Effect.runPromise(trimmed.run(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>()await Effect.runPromise(uncap.run(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
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(withZero.run(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(nonNegative.run(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
- onNone to provide a fallback instead of failing
- 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(mustExist.run(Option.none(), {})))issue._tag // => "MissingKey"