withDecodingDefaultKey<S, R>Makes a struct key optional on the Encoded side and provides a default
Encoded value when the key is missing during decoding.
Details
The key uses optionalKey on the encoded side, so it may be absent from the
input object but not undefined. The default value is specified in terms
of the Encoded type (before any decoding transformations).
Options:
encodingStrategy:"passthrough"(default): include the value in the encoded output."omit": omit the key from the encoded output.
Example (Providing a default for a missing struct key)
import { Effect, Schema } from "effect"
const MySchema = Schema.Struct({
name: Schema.String.pipe(Schema.withDecodingDefaultKey(Effect.succeed("anonymous")))
})
const result = Schema.decodeUnknownSync(MySchema)({})
// result: { name: "anonymous" }export interface interface withDecodingDefaultKey<S extends Constraint, R = never>Makes a struct key optional on the Encoded side and provides a default
Encoded value when the key is missing during decoding.
Details
The key uses optionalKey on the encoded side, so it may be absent from the
input object but not undefined. The default value is specified in terms
of the Encoded type (before any decoding transformations).
Options:
encodingStrategy:
"passthrough" (default): include the value in the encoded output.
"omit": omit the key from the encoded output.
Example (Providing a default for a missing struct key)
import { Effect, Schema } from "effect"
const MySchema = Schema.Struct({
name: Schema.String.pipe(Schema.withDecodingDefaultKey(Effect.succeed("anonymous")))
})
const result = Schema.decodeUnknownSync(MySchema)({})
// result: { name: "anonymous" }
Type-level representation returned by
withDecodingDefaultKey
.
withDecodingDefaultKey<function (type parameter) S in withDecodingDefaultKey<S extends Constraint, R = never>S extends Constraint, function (type parameter) R in withDecodingDefaultKey<S extends Constraint, R = never>R = never>
extends 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) S in withDecodingDefaultKey<S extends Constraint, R = never>S, interface optionalKey<S extends Constraint>Type-level representation returned by
optionalKey
.
Creates an exact optional key schema for struct fields. Unlike optional,
this creates exact optional properties (not | undefined) that can be
completely omitted from the object.
Example (Creating a struct with optional key)
import { Schema } from "effect"
const schema = Schema.Struct({
name: Schema.String,
age: Schema.optionalKey(Schema.Number)
})
// Type: { readonly name: string; readonly age?: number }
type Person = typeof schema["Type"]
optionalKey<interface toEncoded<S extends Constraint>Type-level representation returned by
toEncoded
.
Extracts the encoded-side schema: sets Type to equal the Encoded,
discarding the decoding transformation path.
toEncoded<function (type parameter) S in withDecodingDefaultKey<S extends Constraint, R = never>S>>, function (type parameter) R in withDecodingDefaultKey<S extends Constraint, R = never>R>
{
readonly "Rebuild": interface withDecodingDefaultKey<S extends Constraint, R = never>Makes a struct key optional on the Encoded side and provides a default
Encoded value when the key is missing during decoding.
Details
The key uses optionalKey on the encoded side, so it may be absent from the
input object but not undefined. The default value is specified in terms
of the Encoded type (before any decoding transformations).
Options:
encodingStrategy:
"passthrough" (default): include the value in the encoded output.
"omit": omit the key from the encoded output.
Example (Providing a default for a missing struct key)
import { Effect, Schema } from "effect"
const MySchema = Schema.Struct({
name: Schema.String.pipe(Schema.withDecodingDefaultKey(Effect.succeed("anonymous")))
})
const result = Schema.decodeUnknownSync(MySchema)({})
// result: { name: "anonymous" }
Type-level representation returned by
withDecodingDefaultKey
.
withDecodingDefaultKey<function (type parameter) S in withDecodingDefaultKey<S extends Constraint, R = never>S, function (type parameter) R in withDecodingDefaultKey<S extends Constraint, R = never>R>
}
/**
* Options for {@link withDecodingDefaultKey} and {@link withDecodingDefault}.
*
* **Details**
*
* - `encodingStrategy`:
* - `"passthrough"` (default): pass the value through during encoding
* - `"omit"`: omit the key from the encoded output
*
* @category options
* @since 4.0.0
*/
export type type DecodingDefaultOptions = {
readonly encodingStrategy?:
| "omit"
| "passthrough"
| undefined
}
Options for
withDecodingDefaultKey
and
withDecodingDefault
.
Details
encodingStrategy:
"passthrough" (default): pass the value through during encoding
"omit": omit the key from the encoded output
DecodingDefaultOptions = {
readonly encodingStrategy?: "omit" | "passthrough" | undefinedencodingStrategy?: "omit" | "passthrough" | undefined
}
/**
* Makes a struct key optional on the `Encoded` side and provides a default
* `Encoded` value when the key is missing during decoding.
*
* **Details**
*
* The key uses `optionalKey` on the encoded side, so it may be absent from the
* input object but **not** `undefined`. The default value is specified in terms
* of the `Encoded` type (before any decoding transformations).
*
* Options:
*
* - `encodingStrategy`:
* - `"passthrough"` (default): include the value in the encoded output.
* - `"omit"`: omit the key from the encoded output.
*
* **Example** (Providing a default for a missing struct key)
*
* ```ts
* import { Effect, Schema } from "effect"
*
* const MySchema = Schema.Struct({
* name: Schema.String.pipe(Schema.withDecodingDefaultKey(Effect.succeed("anonymous")))
* })
*
* const result = Schema.decodeUnknownSync(MySchema)({})
* // result: { name: "anonymous" }
* ```
*
* @see {@link withDecodingDefault} for the value-level variant (key absent **or** `undefined`)
* @see {@link withDecodingDefaultTypeKey} for the variant where the default is a `Type` value
* @category decoding
* @since 4.0.0
*/
export function function withDecodingDefaultKey<
S extends Constraint,
R = never
>(
defaultValue: Effect.Effect<
S["Encoded"],
SchemaError,
R
>,
options?: DecodingDefaultOptions
): (self: S) => withDecodingDefaultKey<S, R>
Makes a struct key optional on the Encoded side and provides a default
Encoded value when the key is missing during decoding.
Details
The key uses optionalKey on the encoded side, so it may be absent from the
input object but not undefined. The default value is specified in terms
of the Encoded type (before any decoding transformations).
Options:
encodingStrategy:
"passthrough" (default): include the value in the encoded output.
"omit": omit the key from the encoded output.
Example (Providing a default for a missing struct key)
import { Effect, Schema } from "effect"
const MySchema = Schema.Struct({
name: Schema.String.pipe(Schema.withDecodingDefaultKey(Effect.succeed("anonymous")))
})
const result = Schema.decodeUnknownSync(MySchema)({})
// result: { name: "anonymous" }
withDecodingDefaultKey<function (type parameter) S in withDecodingDefaultKey<S extends Constraint, R = never>(defaultValue: Effect.Effect<S["Encoded"], SchemaError, R>, options?: DecodingDefaultOptions): (self: S) => withDecodingDefaultKey<S, R>S extends Constraint, function (type parameter) R in withDecodingDefaultKey<S extends Constraint, R = never>(defaultValue: Effect.Effect<S["Encoded"], SchemaError, R>, options?: DecodingDefaultOptions): (self: S) => withDecodingDefaultKey<S, R>R = never>(
defaultValue: Effect.Effect<
S["Encoded"],
SchemaError,
R
>
(parameter) defaultValue: {
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; <…;
toString: () => string;
toJSON: () => unknown;
}
defaultValue: import EffectEffect.type Effect.Effect = /*unresolved*/ anyEffect<function (type parameter) S in withDecodingDefaultKey<S extends Constraint, R = never>(defaultValue: Effect.Effect<S["Encoded"], SchemaError, R>, options?: DecodingDefaultOptions): (self: S) => withDecodingDefaultKey<S, R>S["Encoded"], class SchemaErrorclass SchemaError {
message: string;
toString: () => string;
name: string;
stack: string;
cause: unknown;
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; <…;
toJSON: () => unknown;
_tag: Tag;
issue: SchemaIssue.Issue;
}
Error thrown (or returned as the error channel value) when schema decoding
or encoding fails.
Details
The issue field contains a structured
Issue
tree describing
every validation failure, including the path to the problematic value,
expected types, and actual values received. message renders the issue tree
as a human-readable string.
Use
isSchemaError
to narrow an unknown value to SchemaError.
Example (Catching a SchemaError)
import { Schema } from "effect"
try {
Schema.decodeUnknownSync(Schema.Number)("not a number")
} catch (err) {
if (Schema.isSchemaError(err)) {
console.log(err.message)
// Expected number, actual "not a number"
}
}
SchemaError, function (type parameter) R in withDecodingDefaultKey<S extends Constraint, R = never>(defaultValue: Effect.Effect<S["Encoded"], SchemaError, R>, options?: DecodingDefaultOptions): (self: S) => withDecodingDefaultKey<S, R>R>,
options: DecodingDefaultOptionsoptions?: type DecodingDefaultOptions = {
readonly encodingStrategy?:
| "omit"
| "passthrough"
| undefined
}
Options for
withDecodingDefaultKey
and
withDecodingDefault
.
Details
encodingStrategy:
"passthrough" (default): pass the value through during encoding
"omit": omit the key from the encoded output
DecodingDefaultOptions
) {
const const encode: SchemaGetter.Getter<
unknown,
unknown,
never
>
const encode: {
run: (input: Option.Option<E>, options: SchemaAST.ParseOptions) => Effect.Effect<Option.Option<T>, SchemaIssue.Issue, R>;
map: (f: (t: unknown) => T2) => SchemaGetter.Getter<T2, unknown, never>;
compose: (other: SchemaGetter.Getter<T2, unknown, R2>) => SchemaGetter.Getter<T2, unknown, 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 = options: DecodingDefaultOptionsoptions?.encodingStrategy?: "omit" | "passthrough" | undefinedencodingStrategy === "omit" ? import SchemaGetterSchemaGetter.function omit<T>(): Getter<never, T>Creates a getter that always returns None, effectively omitting the value from output.
When to use
Use when you need a schema getter to exclude a field during decoding or
encoding.
Details
- Always returns
Option.None regardless of input.
- Never fails.
Example (Omitting a field during encoding)
import { SchemaGetter } from "effect"
const omitField = SchemaGetter.omit<string>()
omit() : import SchemaGetterSchemaGetter.function passthrough<unknown>(): SchemaGetter.Getter<unknown, unknown, never> (+1 overload)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.
Example (Passing through identity transformations)
import { Schema, SchemaGetter } from "effect"
// No transformation needed — types already match
const StringToString = Schema.String.pipe(
Schema.decodeTo(Schema.String, {
decode: SchemaGetter.passthrough(),
encode: SchemaGetter.passthrough()
})
)
passthrough()
return (self: S extends Constraintself: function (type parameter) S in withDecodingDefaultKey<S extends Constraint, R = never>(defaultValue: Effect.Effect<S["Encoded"], SchemaError, R>, options?: DecodingDefaultOptions): (self: S) => withDecodingDefaultKey<S, R>S): interface withDecodingDefaultKey<S extends Constraint, R = never>Makes a struct key optional on the Encoded side and provides a default
Encoded value when the key is missing during decoding.
Details
The key uses optionalKey on the encoded side, so it may be absent from the
input object but not undefined. The default value is specified in terms
of the Encoded type (before any decoding transformations).
Options:
encodingStrategy:
"passthrough" (default): include the value in the encoded output.
"omit": omit the key from the encoded output.
Example (Providing a default for a missing struct key)
import { Effect, Schema } from "effect"
const MySchema = Schema.Struct({
name: Schema.String.pipe(Schema.withDecodingDefaultKey(Effect.succeed("anonymous")))
})
const result = Schema.decodeUnknownSync(MySchema)({})
// result: { name: "anonymous" }
Type-level representation returned by
withDecodingDefaultKey
.
withDecodingDefaultKey<function (type parameter) S in withDecodingDefaultKey<S extends Constraint, R = never>(defaultValue: Effect.Effect<S["Encoded"], SchemaError, R>, options?: DecodingDefaultOptions): (self: S) => withDecodingDefaultKey<S, R>S, function (type parameter) R in withDecodingDefaultKey<S extends Constraint, R = never>(defaultValue: Effect.Effect<S["Encoded"], SchemaError, R>, options?: DecodingDefaultOptions): (self: S) => withDecodingDefaultKey<S, R>R> => {
return const optionalKey: optionalKeyLambda
<toEncoded<S>>(self: toEncoded<S>) => optionalKey<toEncoded<S>>
Type-level representation returned by
optionalKey
.
Creates an exact optional key schema for struct fields. Unlike optional,
this creates exact optional properties (not | undefined) that can be
completely omitted from the object.
Example (Creating a struct with optional key)
import { Schema } from "effect"
const schema = Schema.Struct({
name: Schema.String,
age: Schema.optionalKey(Schema.Number)
})
// Type: { readonly name: string; readonly age?: number }
type Person = typeof schema["Type"]
optionalKey(const toEncoded: toEncodedLambda
;<S>(self: S) => toEncoded<S>
Type-level representation returned by
toEncoded
.
Extracts the encoded-side schema: sets Type to equal the Encoded,
discarding the decoding transformation path.
toEncoded(self: S extends Constraintself)).pipe(function decodeTo<S, Constraint, never, never>(to: S, transformation: {
readonly decode: SchemaGetter.Getter<NoInfer<S["Encoded"]>, unknown, never>;
readonly encode: SchemaGetter.Getter<unknown, NoInfer<S["Encoded"]>, never>;
}): (from: Constraint) => decodeTo<S, Constraint, never, never> (+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(self: S extends Constraintself, {
decode: SchemaGetter.Getter<
S["Encoded"],
S["Encoded"] | undefined,
R
>
(property) decode: {
run: (input: Option.Option<E>, options: SchemaAST.ParseOptions) => Effect.Effect<Option.Option<T>, SchemaIssue.Issue, R>;
map: (f: (t: S['Encoded']) => T2) => SchemaGetter.Getter<T2, S['Encoded'] | undefined, R>;
compose: (other: SchemaGetter.Getter<T2, S['Encoded'], R2>) => SchemaGetter.Getter<T2, S['Encoded'] | undefined, 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; <…;
}
decode: import SchemaGetterSchemaGetter.function withDefault<T, R = never>(
defaultValue: Effect.Effect<
T,
SchemaIssue.Issue,
R
>
): Getter<T, T | undefined, R>
Creates a getter that replaces undefined values with a default.
When to use
Use when you need a schema getter to provide a fallback for a field that may
be undefined in the encoded input.
Details
- If the input is
Some(undefined) or None, produces Some(T).
- If the input is
Some(value) where value is not undefined, passes it through.
defaultValue is an Effect that will be executed each time a default is needed.
Example (Providing a default value for an optional field)
import { Effect, SchemaGetter } from "effect"
const withZero = SchemaGetter.withDefault(Effect.succeed(0))
// Getter<number, number | undefined>
withDefault(function toIssueEffect<A, R>(
self: Effect.Effect<A, SchemaError, R>
): Effect.Effect<A, SchemaIssue.Issue, R>
toIssueEffect(defaultValue: Effect.Effect<
S["Encoded"],
SchemaError,
R
>
(parameter) defaultValue: {
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; <…;
toString: () => string;
toJSON: () => unknown;
}
defaultValue)),
encode: SchemaGetter.Getter<
unknown,
unknown,
never
>
(property) encode: {
run: (input: Option.Option<E>, options: SchemaAST.ParseOptions) => Effect.Effect<Option.Option<T>, SchemaIssue.Issue, R>;
map: (f: (t: unknown) => T2) => SchemaGetter.Getter<T2, unknown, never>;
compose: (other: SchemaGetter.Getter<T2, unknown, R2>) => SchemaGetter.Getter<T2, unknown, 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
}))
}
}