<To extends Constraint>(to: To): <From extends Constraint>(
from: From
) => decodeTo<From, To>
<To extends Constraint, From extends Constraint, RD = never, RE = never>(
to: To,
transformation: {
readonly decode: SchemaGetter.Getter<
NoInfer<From["Encoded"]>,
NoInfer<To["Type"]>,
RD
>
readonly encode: SchemaGetter.Getter<
NoInfer<To["Type"]>,
NoInfer<From["Encoded"]>,
RE
>
}
): (from: From) => decodeTo<From, To, RD, RE>Reverses a schema transformation so the encoded schema is supplied first.
When to use
Use to define a transformation by naming the encoded schema before the decoded schema.
Details
encodeTo(to)(from) is equivalent to to.pipe(decodeTo(from)). The from
schema acts as the target decoded schema and to acts as the encoded source.
Example (Encoding a number back to a string)
import { Schema, SchemaGetter } from "effect"
const NumberFromString = Schema.Number.pipe(
Schema.encodeTo(Schema.String, {
decode: SchemaGetter.transform((s: string) => Number(s)),
encode: SchemaGetter.transform((n: number) => String(n))
})
)export function function encodeTo<To extends Constraint>(to: To): <From extends Constraint>(from: From) => decodeTo<From, To> (+1 overload)Reverses a schema transformation so the encoded schema is supplied first.
When to use
Use to define a transformation by naming the encoded schema before the
decoded schema.
Details
encodeTo(to)(from) is equivalent to to.pipe(decodeTo(from)). The from
schema acts as the target decoded schema and to acts as the encoded source.
Example (Encoding a number back to a string)
import { Schema, SchemaGetter } from "effect"
const NumberFromString = Schema.Number.pipe(
Schema.encodeTo(Schema.String, {
decode: SchemaGetter.transform((s: string) => Number(s)),
encode: SchemaGetter.transform((n: number) => String(n))
})
)
encodeTo<function (type parameter) To in encodeTo<To extends Constraint>(to: To): <From extends Constraint>(from: From) => decodeTo<From, To>To extends Constraint>(
to: To extends Constraintto: function (type parameter) To in encodeTo<To extends Constraint>(to: To): <From extends Constraint>(from: From) => decodeTo<From, To>To
): <function (type parameter) From in <From extends Constraint>(from: From): decodeTo<From, To>From extends Constraint>(from: From extends Constraintfrom: function (type parameter) From in <From extends Constraint>(from: From): decodeTo<From, To>From) => interface decodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>Creates a schema that transforms from a source schema to a target schema.
When to use
Use when decoding should change the schema's decoded type or encoded shape,
with an optional custom bidirectional transformation.
Details
Call it with the target schema to and then pipe the source schema from
into the returned function. The resulting schema decodes from
From["Encoded"] to To["Type"] and encodes from To["Type"] back to
From["Encoded"].
When no transformation is provided, SchemaTransformation.passthrough() is
used, so From["Type"] must already be compatible with To["Encoded"].
The resulting schema combines decoding and encoding services from both
schemas and any custom transformation.
Gotchas
In a custom transformation, decode maps From["Type"] to To["Encoded"]
and is used on the encoding path, while encode maps To["Encoded"] to
From["Type"] and is used on the decoding path.
Example (Transforming strings to numbers with a schema transformation)
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))
}
)
)
const result = Schema.decodeUnknownSync(NumberFromString)("123")
// result: 123
Type-level representation returned by
decodeTo
.
decodeTo<function (type parameter) From in <From extends Constraint>(from: From): decodeTo<From, To>From, function (type parameter) To in encodeTo<To extends Constraint>(to: To): <From extends Constraint>(from: From) => decodeTo<From, To>To>
export function function encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation: {
readonly decode: SchemaGetter.Getter<NoInfer<From["Encoded"]>, NoInfer<To["Type"]>, RD>;
readonly encode: SchemaGetter.Getter<NoInfer<To["Type"]>, NoInfer<From["Encoded"]>, RE>;
}): (from: From) => decodeTo<From, To, RD, RE> (+1 overload)
Reverses a schema transformation so the encoded schema is supplied first.
When to use
Use to define a transformation by naming the encoded schema before the
decoded schema.
Details
encodeTo(to)(from) is equivalent to to.pipe(decodeTo(from)). The from
schema acts as the target decoded schema and to acts as the encoded source.
Example (Encoding a number back to a string)
import { Schema, SchemaGetter } from "effect"
const NumberFromString = Schema.Number.pipe(
Schema.encodeTo(Schema.String, {
decode: SchemaGetter.transform((s: string) => Number(s)),
encode: SchemaGetter.transform((n: number) => String(n))
})
)
encodeTo<function (type parameter) To in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation: {
readonly decode: SchemaGetter.Getter<NoInfer<From["Encoded"]>, NoInfer<To["Type"]>, RD>;
readonly encode: SchemaGetter.Getter<NoInfer<To["Type"]>, NoInfer<From["Encoded"]>, RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
To extends Constraint, function (type parameter) From in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation: {
readonly decode: SchemaGetter.Getter<NoInfer<From["Encoded"]>, NoInfer<To["Type"]>, RD>;
readonly encode: SchemaGetter.Getter<NoInfer<To["Type"]>, NoInfer<From["Encoded"]>, RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
From extends Constraint, function (type parameter) RD in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation: {
readonly decode: SchemaGetter.Getter<NoInfer<From["Encoded"]>, NoInfer<To["Type"]>, RD>;
readonly encode: SchemaGetter.Getter<NoInfer<To["Type"]>, NoInfer<From["Encoded"]>, RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
RD = never, function (type parameter) RE in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation: {
readonly decode: SchemaGetter.Getter<NoInfer<From["Encoded"]>, NoInfer<To["Type"]>, RD>;
readonly encode: SchemaGetter.Getter<NoInfer<To["Type"]>, NoInfer<From["Encoded"]>, RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
RE = never>(
to: To extends Constraintto: function (type parameter) To in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation: {
readonly decode: SchemaGetter.Getter<NoInfer<From["Encoded"]>, NoInfer<To["Type"]>, RD>;
readonly encode: SchemaGetter.Getter<NoInfer<To["Type"]>, NoInfer<From["Encoded"]>, RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
To,
transformation: {
readonly decode: SchemaGetter.Getter<
NoInfer<From["Encoded"]>,
NoInfer<To["Type"]>,
RD
>
readonly encode: SchemaGetter.Getter<
NoInfer<To["Type"]>,
NoInfer<From["Encoded"]>,
RE
>
}
transformation: {
readonly decode: SchemaGetter.Getter<
NoInfer<From["Encoded"]>,
NoInfer<To["Type"]>,
RD
>
(property) decode: {
run: (input: Option.Option<E>, options: SchemaAST.ParseOptions) => Effect.Effect<Option.Option<T>, SchemaIssue.Issue, R>;
map: (f: (t: NoInfer<From['Encoded']>) => T2) => SchemaGetter.Getter<T2, NoInfer<To['Type']>, RD>;
compose: (other: SchemaGetter.Getter<T2, NoInfer<From['Encoded']>, R2>) => SchemaGetter.Getter<T2, NoInfer<To['Type']>, RD | R2>;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
decode: import SchemaGetterSchemaGetter.class Getter<out T, in E, R = never>class Getter {
run: (input: Option.Option<E>, options: SchemaAST.ParseOptions) => Effect.Effect<Option.Option<T>, SchemaIssue.Issue, R>;
map: <T2>(f: (t: T) => T2) => Getter<T2, E, R>;
compose: <T2, R2>(other: Getter<T2, T, R2>) => Getter<T2, E, R | R2>;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
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.
Example (Creating and composing getters)
import { 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)
// composed: Getter<number, string> — parses then doubles
Getter<type NoInfer<T> = intrinsicMarker for non-inference type position
NoInfer<function (type parameter) From in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation: {
readonly decode: SchemaGetter.Getter<NoInfer<From["Encoded"]>, NoInfer<To["Type"]>, RD>;
readonly encode: SchemaGetter.Getter<NoInfer<To["Type"]>, NoInfer<From["Encoded"]>, RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
From["Encoded"]>, type NoInfer<T> = intrinsicMarker for non-inference type position
NoInfer<function (type parameter) To in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation: {
readonly decode: SchemaGetter.Getter<NoInfer<From["Encoded"]>, NoInfer<To["Type"]>, RD>;
readonly encode: SchemaGetter.Getter<NoInfer<To["Type"]>, NoInfer<From["Encoded"]>, RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
To["Type"]>, function (type parameter) RD in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation: {
readonly decode: SchemaGetter.Getter<NoInfer<From["Encoded"]>, NoInfer<To["Type"]>, RD>;
readonly encode: SchemaGetter.Getter<NoInfer<To["Type"]>, NoInfer<From["Encoded"]>, RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
RD>
readonly encode: SchemaGetter.Getter<
NoInfer<To["Type"]>,
NoInfer<From["Encoded"]>,
RE
>
(property) encode: {
run: (input: Option.Option<E>, options: SchemaAST.ParseOptions) => Effect.Effect<Option.Option<T>, SchemaIssue.Issue, R>;
map: (f: (t: NoInfer<To['Type']>) => T2) => SchemaGetter.Getter<T2, NoInfer<From['Encoded']>, RE>;
compose: (other: SchemaGetter.Getter<T2, NoInfer<To['Type']>, R2>) => SchemaGetter.Getter<T2, NoInfer<From['Encoded']>, RE | R2>;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
encode: import SchemaGetterSchemaGetter.class Getter<out T, in E, R = never>class Getter {
run: (input: Option.Option<E>, options: SchemaAST.ParseOptions) => Effect.Effect<Option.Option<T>, SchemaIssue.Issue, R>;
map: <T2>(f: (t: T) => T2) => Getter<T2, E, R>;
compose: <T2, R2>(other: Getter<T2, T, R2>) => Getter<T2, E, R | R2>;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
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.
Example (Creating and composing getters)
import { 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)
// composed: Getter<number, string> — parses then doubles
Getter<type NoInfer<T> = intrinsicMarker for non-inference type position
NoInfer<function (type parameter) To in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation: {
readonly decode: SchemaGetter.Getter<NoInfer<From["Encoded"]>, NoInfer<To["Type"]>, RD>;
readonly encode: SchemaGetter.Getter<NoInfer<To["Type"]>, NoInfer<From["Encoded"]>, RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
To["Type"]>, type NoInfer<T> = intrinsicMarker for non-inference type position
NoInfer<function (type parameter) From in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation: {
readonly decode: SchemaGetter.Getter<NoInfer<From["Encoded"]>, NoInfer<To["Type"]>, RD>;
readonly encode: SchemaGetter.Getter<NoInfer<To["Type"]>, NoInfer<From["Encoded"]>, RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
From["Encoded"]>, function (type parameter) RE in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation: {
readonly decode: SchemaGetter.Getter<NoInfer<From["Encoded"]>, NoInfer<To["Type"]>, RD>;
readonly encode: SchemaGetter.Getter<NoInfer<To["Type"]>, NoInfer<From["Encoded"]>, RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
RE>
}
): (from: From extends Constraintfrom: function (type parameter) From in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation: {
readonly decode: SchemaGetter.Getter<NoInfer<From["Encoded"]>, NoInfer<To["Type"]>, RD>;
readonly encode: SchemaGetter.Getter<NoInfer<To["Type"]>, NoInfer<From["Encoded"]>, RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
From) => interface decodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>Creates a schema that transforms from a source schema to a target schema.
When to use
Use when decoding should change the schema's decoded type or encoded shape,
with an optional custom bidirectional transformation.
Details
Call it with the target schema to and then pipe the source schema from
into the returned function. The resulting schema decodes from
From["Encoded"] to To["Type"] and encodes from To["Type"] back to
From["Encoded"].
When no transformation is provided, SchemaTransformation.passthrough() is
used, so From["Type"] must already be compatible with To["Encoded"].
The resulting schema combines decoding and encoding services from both
schemas and any custom transformation.
Gotchas
In a custom transformation, decode maps From["Type"] to To["Encoded"]
and is used on the encoding path, while encode maps To["Encoded"] to
From["Type"] and is used on the decoding path.
Example (Transforming strings to numbers with a schema transformation)
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))
}
)
)
const result = Schema.decodeUnknownSync(NumberFromString)("123")
// result: 123
Type-level representation returned by
decodeTo
.
decodeTo<function (type parameter) From in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation: {
readonly decode: SchemaGetter.Getter<NoInfer<From["Encoded"]>, NoInfer<To["Type"]>, RD>;
readonly encode: SchemaGetter.Getter<NoInfer<To["Type"]>, NoInfer<From["Encoded"]>, RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
From, function (type parameter) To in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation: {
readonly decode: SchemaGetter.Getter<NoInfer<From["Encoded"]>, NoInfer<To["Type"]>, RD>;
readonly encode: SchemaGetter.Getter<NoInfer<To["Type"]>, NoInfer<From["Encoded"]>, RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
To, function (type parameter) RD in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation: {
readonly decode: SchemaGetter.Getter<NoInfer<From["Encoded"]>, NoInfer<To["Type"]>, RD>;
readonly encode: SchemaGetter.Getter<NoInfer<To["Type"]>, NoInfer<From["Encoded"]>, RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
RD, function (type parameter) RE in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation: {
readonly decode: SchemaGetter.Getter<NoInfer<From["Encoded"]>, NoInfer<To["Type"]>, RD>;
readonly encode: SchemaGetter.Getter<NoInfer<To["Type"]>, NoInfer<From["Encoded"]>, RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
RE>
export function function encodeTo<To extends Constraint>(to: To): <From extends Constraint>(from: From) => decodeTo<From, To> (+1 overload)Reverses a schema transformation so the encoded schema is supplied first.
When to use
Use to define a transformation by naming the encoded schema before the
decoded schema.
Details
encodeTo(to)(from) is equivalent to to.pipe(decodeTo(from)). The from
schema acts as the target decoded schema and to acts as the encoded source.
Example (Encoding a number back to a string)
import { Schema, SchemaGetter } from "effect"
const NumberFromString = Schema.Number.pipe(
Schema.encodeTo(Schema.String, {
decode: SchemaGetter.transform((s: string) => Number(s)),
encode: SchemaGetter.transform((n: number) => String(n))
})
)
encodeTo<function (type parameter) To in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation?: {
readonly decode: SchemaGetter.Getter<From["Encoded"], To["Type"], RD>;
readonly encode: SchemaGetter.Getter<To["Type"], From["Encoded"], RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
To extends Constraint, function (type parameter) From in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation?: {
readonly decode: SchemaGetter.Getter<From["Encoded"], To["Type"], RD>;
readonly encode: SchemaGetter.Getter<To["Type"], From["Encoded"], RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
From extends Constraint, function (type parameter) RD in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation?: {
readonly decode: SchemaGetter.Getter<From["Encoded"], To["Type"], RD>;
readonly encode: SchemaGetter.Getter<To["Type"], From["Encoded"], RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
RD = never, function (type parameter) RE in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation?: {
readonly decode: SchemaGetter.Getter<From["Encoded"], To["Type"], RD>;
readonly encode: SchemaGetter.Getter<To["Type"], From["Encoded"], RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
RE = never>(
to: To extends Constraintto: function (type parameter) To in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation?: {
readonly decode: SchemaGetter.Getter<From["Encoded"], To["Type"], RD>;
readonly encode: SchemaGetter.Getter<To["Type"], From["Encoded"], RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
To,
transformation: {
readonly decode: SchemaGetter.Getter<
From["Encoded"],
To["Type"],
RD
>
readonly encode: SchemaGetter.Getter<
To["Type"],
From["Encoded"],
RE
>
}
transformation?: {
readonly decode: SchemaGetter.Getter<
From["Encoded"],
To["Type"],
RD
>
(property) decode: {
run: (input: Option.Option<E>, options: SchemaAST.ParseOptions) => Effect.Effect<Option.Option<T>, SchemaIssue.Issue, R>;
map: (f: (t: From['Encoded']) => T2) => SchemaGetter.Getter<T2, To['Type'], RD>;
compose: (other: SchemaGetter.Getter<T2, From['Encoded'], R2>) => SchemaGetter.Getter<T2, To['Type'], RD | R2>;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
decode: import SchemaGetterSchemaGetter.class Getter<out T, in E, R = never>class Getter {
run: (input: Option.Option<E>, options: SchemaAST.ParseOptions) => Effect.Effect<Option.Option<T>, SchemaIssue.Issue, R>;
map: <T2>(f: (t: T) => T2) => Getter<T2, E, R>;
compose: <T2, R2>(other: Getter<T2, T, R2>) => Getter<T2, E, R | R2>;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
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.
Example (Creating and composing getters)
import { 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)
// composed: Getter<number, string> — parses then doubles
Getter<function (type parameter) From in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation?: {
readonly decode: SchemaGetter.Getter<From["Encoded"], To["Type"], RD>;
readonly encode: SchemaGetter.Getter<To["Type"], From["Encoded"], RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
From["Encoded"], function (type parameter) To in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation?: {
readonly decode: SchemaGetter.Getter<From["Encoded"], To["Type"], RD>;
readonly encode: SchemaGetter.Getter<To["Type"], From["Encoded"], RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
To["Type"], function (type parameter) RD in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation?: {
readonly decode: SchemaGetter.Getter<From["Encoded"], To["Type"], RD>;
readonly encode: SchemaGetter.Getter<To["Type"], From["Encoded"], RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
RD>
readonly encode: SchemaGetter.Getter<
To["Type"],
From["Encoded"],
RE
>
(property) encode: {
run: (input: Option.Option<E>, options: SchemaAST.ParseOptions) => Effect.Effect<Option.Option<T>, SchemaIssue.Issue, R>;
map: (f: (t: To['Type']) => T2) => SchemaGetter.Getter<T2, From['Encoded'], RE>;
compose: (other: SchemaGetter.Getter<T2, To['Type'], R2>) => SchemaGetter.Getter<T2, From['Encoded'], RE | R2>;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
encode: import SchemaGetterSchemaGetter.class Getter<out T, in E, R = never>class Getter {
run: (input: Option.Option<E>, options: SchemaAST.ParseOptions) => Effect.Effect<Option.Option<T>, SchemaIssue.Issue, R>;
map: <T2>(f: (t: T) => T2) => Getter<T2, E, R>;
compose: <T2, R2>(other: Getter<T2, T, R2>) => Getter<T2, E, R | R2>;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
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.
Example (Creating and composing getters)
import { 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)
// composed: Getter<number, string> — parses then doubles
Getter<function (type parameter) To in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation?: {
readonly decode: SchemaGetter.Getter<From["Encoded"], To["Type"], RD>;
readonly encode: SchemaGetter.Getter<To["Type"], From["Encoded"], RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
To["Type"], function (type parameter) From in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation?: {
readonly decode: SchemaGetter.Getter<From["Encoded"], To["Type"], RD>;
readonly encode: SchemaGetter.Getter<To["Type"], From["Encoded"], RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
From["Encoded"], function (type parameter) RE in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation?: {
readonly decode: SchemaGetter.Getter<From["Encoded"], To["Type"], RD>;
readonly encode: SchemaGetter.Getter<To["Type"], From["Encoded"], RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
RE>
}
) {
return (from: From extends Constraintfrom: function (type parameter) From in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation?: {
readonly decode: SchemaGetter.Getter<From["Encoded"], To["Type"], RD>;
readonly encode: SchemaGetter.Getter<To["Type"], From["Encoded"], RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
From): interface decodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>Creates a schema that transforms from a source schema to a target schema.
When to use
Use when decoding should change the schema's decoded type or encoded shape,
with an optional custom bidirectional transformation.
Details
Call it with the target schema to and then pipe the source schema from
into the returned function. The resulting schema decodes from
From["Encoded"] to To["Type"] and encodes from To["Type"] back to
From["Encoded"].
When no transformation is provided, SchemaTransformation.passthrough() is
used, so From["Type"] must already be compatible with To["Encoded"].
The resulting schema combines decoding and encoding services from both
schemas and any custom transformation.
Gotchas
In a custom transformation, decode maps From["Type"] to To["Encoded"]
and is used on the encoding path, while encode maps To["Encoded"] to
From["Type"] and is used on the decoding path.
Example (Transforming strings to numbers with a schema transformation)
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))
}
)
)
const result = Schema.decodeUnknownSync(NumberFromString)("123")
// result: 123
Type-level representation returned by
decodeTo
.
decodeTo<function (type parameter) From in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation?: {
readonly decode: SchemaGetter.Getter<From["Encoded"], To["Type"], RD>;
readonly encode: SchemaGetter.Getter<To["Type"], From["Encoded"], RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
From, function (type parameter) To in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation?: {
readonly decode: SchemaGetter.Getter<From["Encoded"], To["Type"], RD>;
readonly encode: SchemaGetter.Getter<To["Type"], From["Encoded"], RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
To, function (type parameter) RD in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation?: {
readonly decode: SchemaGetter.Getter<From["Encoded"], To["Type"], RD>;
readonly encode: SchemaGetter.Getter<To["Type"], From["Encoded"], RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
RD, function (type parameter) RE in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation?: {
readonly decode: SchemaGetter.Getter<From["Encoded"], To["Type"], RD>;
readonly encode: SchemaGetter.Getter<To["Type"], From["Encoded"], RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
RE> => {
return transformation: {
readonly decode: SchemaGetter.Getter<
From["Encoded"],
To["Type"],
RD
>
readonly encode: SchemaGetter.Getter<
To["Type"],
From["Encoded"],
RE
>
}
transformation ?
function decodeTo<From, To, RD, RE>(to: From, transformation: {
readonly decode: SchemaGetter.Getter<NoInfer<From["Encoded"]>, NoInfer<To["Type"]>, RD>;
readonly encode: SchemaGetter.Getter<NoInfer<To["Type"]>, NoInfer<From["Encoded"]>, RE>;
}): (from: To) => decodeTo<From, To, RD, RE> (+1 overload)
Creates a schema that transforms from a source schema to a target schema.
When to use
Use when decoding should change the schema's decoded type or encoded shape,
with an optional custom bidirectional transformation.
Details
Call it with the target schema to and then pipe the source schema from
into the returned function. The resulting schema decodes from
From["Encoded"] to To["Type"] and encodes from To["Type"] back to
From["Encoded"].
When no transformation is provided, SchemaTransformation.passthrough() is
used, so From["Type"] must already be compatible with To["Encoded"].
The resulting schema combines decoding and encoding services from both
schemas and any custom transformation.
Gotchas
In a custom transformation, decode maps From["Type"] to To["Encoded"]
and is used on the encoding path, while encode maps To["Encoded"] to
From["Type"] and is used on the decoding path.
Example (Transforming strings to numbers with a schema transformation)
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))
}
)
)
const result = Schema.decodeUnknownSync(NumberFromString)("123")
// result: 123
decodeTo<function (type parameter) From in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation?: {
readonly decode: SchemaGetter.Getter<From["Encoded"], To["Type"], RD>;
readonly encode: SchemaGetter.Getter<To["Type"], From["Encoded"], RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
From, function (type parameter) To in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation?: {
readonly decode: SchemaGetter.Getter<From["Encoded"], To["Type"], RD>;
readonly encode: SchemaGetter.Getter<To["Type"], From["Encoded"], RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
To, function (type parameter) RD in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation?: {
readonly decode: SchemaGetter.Getter<From["Encoded"], To["Type"], RD>;
readonly encode: SchemaGetter.Getter<To["Type"], From["Encoded"], RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
RD, function (type parameter) RE in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation?: {
readonly decode: SchemaGetter.Getter<From["Encoded"], To["Type"], RD>;
readonly encode: SchemaGetter.Getter<To["Type"], From["Encoded"], RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
RE>(from: From extends Constraintfrom, transformation: {
readonly decode: SchemaGetter.Getter<
From["Encoded"],
To["Type"],
RD
>
readonly encode: SchemaGetter.Getter<
To["Type"],
From["Encoded"],
RE
>
}
transformation)(to: To extends Constraintto) :
function decodeTo<From>(to: From): <From>(from: From) => compose<From, From> (+1 overload)Creates a schema that transforms from a source schema to a target schema.
When to use
Use when decoding should change the schema's decoded type or encoded shape,
with an optional custom bidirectional transformation.
Details
Call it with the target schema to and then pipe the source schema from
into the returned function. The resulting schema decodes from
From["Encoded"] to To["Type"] and encodes from To["Type"] back to
From["Encoded"].
When no transformation is provided, SchemaTransformation.passthrough() is
used, so From["Type"] must already be compatible with To["Encoded"].
The resulting schema combines decoding and encoding services from both
schemas and any custom transformation.
Gotchas
In a custom transformation, decode maps From["Type"] to To["Encoded"]
and is used on the encoding path, while encode maps To["Encoded"] to
From["Type"] and is used on the decoding path.
Example (Transforming strings to numbers with a schema transformation)
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))
}
)
)
const result = Schema.decodeUnknownSync(NumberFromString)("123")
// result: 123
decodeTo<function (type parameter) From in encodeTo<To extends Constraint, From extends Constraint, RD = never, RE = never>(to: To, transformation?: {
readonly decode: SchemaGetter.Getter<From["Encoded"], To["Type"], RD>;
readonly encode: SchemaGetter.Getter<To["Type"], From["Encoded"], RE>;
}): (from: From) => decodeTo<From, To, RD, RE>
From>(from: From extends Constraintfrom)(to: To extends Constraintto)
}
}