encodeKeys<S, M>Renames struct keys in the encoded form without changing the decoded type.
Details
Takes a partial mapping { decodedKey: encodedKey } and produces a
transformation schema that decodes from the renamed keys and encodes back to
the renamed keys. Keys not present in the mapping are left unchanged.
If two existing fields would produce the same encoded key, construction
fails.
Example (Renaming name to full_name in the encoded form)
import { Schema } from "effect"
const Person = Schema.Struct({ name: Schema.String, age: Schema.Number })
const Encoded = Person.pipe(Schema.encodeKeys({ name: "full_name" }))
// Decodes { full_name: "Alice", age: 30 } → { name: "Alice", age: 30 }
const alice = Schema.decodeUnknownSync(Encoded)({ full_name: "Alice", age: 30 })
console.log(alice)
// { name: 'Alice', age: 30 }export interface interface encodeKeys<S extends Constraint & { readonly fields: Struct.Fields; }, M extends { readonly [K in keyof S["fields"]]?: PropertyKey; }>Renames struct keys in the encoded form without changing the decoded type.
Details
Takes a partial mapping { decodedKey: encodedKey } and produces a
transformation schema that decodes from the renamed keys and encodes back to
the renamed keys. Keys not present in the mapping are left unchanged.
If two existing fields would produce the same encoded key, construction
fails.
Example (Renaming name to full_name in the encoded form)
import { Schema } from "effect"
const Person = Schema.Struct({ name: Schema.String, age: Schema.Number })
const Encoded = Person.pipe(Schema.encodeKeys({ name: "full_name" }))
// Decodes { full_name: "Alice", age: 30 } → { name: "Alice", age: 30 }
const alice = Schema.decodeUnknownSync(Encoded)({ full_name: "Alice", age: 30 })
console.log(alice)
// { name: 'Alice', age: 30 }
Type-level representation returned by
encodeKeys
.
encodeKeys<
function (type parameter) S in encodeKeys<S extends Constraint & { readonly fields: Struct.Fields; }, M extends { readonly [K in keyof S["fields"]]?: PropertyKey; }>S extends Constraint & { readonly fields: Struct.Fieldsfields: Struct.type Struct<Fields extends Struct.Fields>.Fields = {
readonly [x: string]: Constraint;
readonly [x: number]: Constraint;
readonly [x: symbol]: Constraint;
}
Constraint for a struct field map: an object whose values are schemas.
Fields },
function (type parameter) M in encodeKeys<S extends Constraint & { readonly fields: Struct.Fields; }, M extends { readonly [K in keyof S["fields"]]?: PropertyKey; }>M extends { readonly [function (type parameter) KK in keyof function (type parameter) S in encodeKeys<S extends Constraint & { readonly fields: Struct.Fields; }, M extends { readonly [K in keyof S["fields"]]?: PropertyKey; }>S["fields"]]?: type PropertyKey =
| string
| number
| symbol
PropertyKey }
> 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 encodeKeys<S extends Constraint & { readonly fields: Struct.Fields; }, M extends { readonly [K in keyof S["fields"]]?: PropertyKey; }>S,
interface Struct<Fields extends Struct.Fields>Defines a struct schema from a map of field schemas.
Details
Each field value is a schema. Use
optionalKey
or
optional
to
mark fields as optional, and
mutableKey
to mark them as mutable.
The resulting schema's Type is a readonly object type with the fields'
decoded types. The Encoded form mirrors the field schemas' encoded types.
Example (Defining a basic struct)
import { Schema } from "effect"
const Person = Schema.Struct({
name: Schema.String,
age: Schema.Number,
email: Schema.optionalKey(Schema.String)
})
// { readonly name: string; readonly age: number; readonly email?: string }
type Person = typeof Person.Type
const alice = Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 })
console.log(alice)
// { name: 'Alice', age: 30 }
Namespace for struct field type utilities.
Details
These types compute the decoded Type, encoded Encoded, and constructor
input MakeIn of a
Struct
from its field map, handling optional,
mutable, and other field modifiers automatically.
Struct.Fields — constraint for the field map object
Struct.Type<F> — decoded type of the struct
Struct.Encoded<F> — encoded type of the struct
Struct.MakeIn<F> — constructor input (optional/defaulted fields may be omitted)
Struct.DecodingServices<F> / Struct.EncodingServices<F> — required services
Type-level representation returned by
Struct
.
Struct<
{
[
function (type parameter) KK in keyof function (type parameter) S in encodeKeys<S extends Constraint & { readonly fields: Struct.Fields; }, M extends { readonly [K in keyof S["fields"]]?: PropertyKey; }>S["fields"] as function (type parameter) KK extends keyof function (type parameter) M in encodeKeys<S extends Constraint & { readonly fields: Struct.Fields; }, M extends { readonly [K in keyof S["fields"]]?: PropertyKey; }>M ? function (type parameter) M in encodeKeys<S extends Constraint & { readonly fields: Struct.Fields; }, M extends { readonly [K in keyof S["fields"]]?: PropertyKey; }>M[function (type parameter) KK] extends type PropertyKey =
| string
| number
| symbol
PropertyKey ? function (type parameter) M in encodeKeys<S extends Constraint & { readonly fields: Struct.Fields; }, M extends { readonly [K in keyof S["fields"]]?: PropertyKey; }>M[function (type parameter) KK] : function (type parameter) KK : function (type parameter) KK
]: 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 encodeKeys<S extends Constraint & { readonly fields: Struct.Fields; }, M extends { readonly [K in keyof S["fields"]]?: PropertyKey; }>S["fields"][function (type parameter) KK]>
}
>
>
{}
const const canonicalPropertyKey: (
key: PropertyKey
) => string | symbol
canonicalPropertyKey = (key: PropertyKeykey: type PropertyKey =
| string
| number
| symbol
PropertyKey): string | symbol =>
typeof key: PropertyKeykey === "symbol" ? key: symbolkey : module globalThisglobalThis.var String: StringConstructor
;(value?: any) => string
Allows manipulation and formatting of text strings and determination and location of substrings within strings.
String(key: string | numberkey)
/**
* Renames struct keys in the encoded form without changing the decoded type.
*
* **Details**
*
* Takes a partial mapping `{ decodedKey: encodedKey }` and produces a
* transformation schema that decodes from the renamed keys and encodes back to
* the renamed keys. Keys not present in the mapping are left unchanged.
* If two existing fields would produce the same encoded key, construction
* fails.
*
* **Example** (Renaming `name` to `full_name` in the encoded form)
*
* ```ts
* import { Schema } from "effect"
*
* const Person = Schema.Struct({ name: Schema.String, age: Schema.Number })
* const Encoded = Person.pipe(Schema.encodeKeys({ name: "full_name" }))
*
* // Decodes { full_name: "Alice", age: 30 } → { name: "Alice", age: 30 }
* const alice = Schema.decodeUnknownSync(Encoded)({ full_name: "Alice", age: 30 })
* console.log(alice)
* // { name: 'Alice', age: 30 }
* ```
*
* @category transforming
* @since 4.0.0
*/
export function function encodeKeys<
S extends Constraint & {
readonly fields: Struct.Fields
},
M extends {
readonly [K in keyof S["fields"]]?: PropertyKey
}
>(mapping: M): (self: S) => encodeKeys<S, M>
Renames struct keys in the encoded form without changing the decoded type.
Details
Takes a partial mapping { decodedKey: encodedKey } and produces a
transformation schema that decodes from the renamed keys and encodes back to
the renamed keys. Keys not present in the mapping are left unchanged.
If two existing fields would produce the same encoded key, construction
fails.
Example (Renaming name to full_name in the encoded form)
import { Schema } from "effect"
const Person = Schema.Struct({ name: Schema.String, age: Schema.Number })
const Encoded = Person.pipe(Schema.encodeKeys({ name: "full_name" }))
// Decodes { full_name: "Alice", age: 30 } → { name: "Alice", age: 30 }
const alice = Schema.decodeUnknownSync(Encoded)({ full_name: "Alice", age: 30 })
console.log(alice)
// { name: 'Alice', age: 30 }
encodeKeys<
function (type parameter) S in encodeKeys<S extends Constraint & {
readonly fields: Struct.Fields;
}, const M extends { readonly [K in keyof S["fields"]]?: PropertyKey; }>(mapping: M): (self: S) => encodeKeys<S, M>
S extends Constraint & { readonly fields: Struct.Fieldsfields: Struct.type Struct<Fields extends Struct.Fields>.Fields = {
readonly [x: string]: Constraint;
readonly [x: number]: Constraint;
readonly [x: symbol]: Constraint;
}
Constraint for a struct field map: an object whose values are schemas.
Fields },
const function (type parameter) M in encodeKeys<S extends Constraint & {
readonly fields: Struct.Fields;
}, const M extends { readonly [K in keyof S["fields"]]?: PropertyKey; }>(mapping: M): (self: S) => encodeKeys<S, M>
M extends { readonly [function (type parameter) KK in keyof function (type parameter) S in encodeKeys<S extends Constraint & {
readonly fields: Struct.Fields;
}, const M extends { readonly [K in keyof S["fields"]]?: PropertyKey; }>(mapping: M): (self: S) => encodeKeys<S, M>
S["fields"]]?: type PropertyKey =
| string
| number
| symbol
PropertyKey }
>(mapping: const M extends { readonly [K in keyof S["fields"]]?: PropertyKey; }mapping: function (type parameter) M in encodeKeys<S extends Constraint & {
readonly fields: Struct.Fields;
}, const M extends { readonly [K in keyof S["fields"]]?: PropertyKey; }>(mapping: M): (self: S) => encodeKeys<S, M>
M) {
return function(self: S extends Constraint & { readonly fields: Struct.Fields; }self: function (type parameter) S in encodeKeys<S extends Constraint & {
readonly fields: Struct.Fields;
}, const M extends { readonly [K in keyof S["fields"]]?: PropertyKey; }>(mapping: M): (self: S) => encodeKeys<S, M>
S): interface encodeKeys<S extends Constraint & { readonly fields: Struct.Fields; }, M extends { readonly [K in keyof S["fields"]]?: PropertyKey; }>Renames struct keys in the encoded form without changing the decoded type.
Details
Takes a partial mapping { decodedKey: encodedKey } and produces a
transformation schema that decodes from the renamed keys and encodes back to
the renamed keys. Keys not present in the mapping are left unchanged.
If two existing fields would produce the same encoded key, construction
fails.
Example (Renaming name to full_name in the encoded form)
import { Schema } from "effect"
const Person = Schema.Struct({ name: Schema.String, age: Schema.Number })
const Encoded = Person.pipe(Schema.encodeKeys({ name: "full_name" }))
// Decodes { full_name: "Alice", age: 30 } → { name: "Alice", age: 30 }
const alice = Schema.decodeUnknownSync(Encoded)({ full_name: "Alice", age: 30 })
console.log(alice)
// { name: 'Alice', age: 30 }
Type-level representation returned by
encodeKeys
.
encodeKeys<function (type parameter) S in encodeKeys<S extends Constraint & {
readonly fields: Struct.Fields;
}, const M extends { readonly [K in keyof S["fields"]]?: PropertyKey; }>(mapping: M): (self: S) => encodeKeys<S, M>
S, function (type parameter) M in encodeKeys<S extends Constraint & {
readonly fields: Struct.Fields;
}, const M extends { readonly [K in keyof S["fields"]]?: PropertyKey; }>(mapping: M): (self: S) => encodeKeys<S, M>
M> {
const const fields: anyfields: any = {}
const const appliedMapping: anyappliedMapping: any = {}
const const reverseMapping: anyreverseMapping: any = {}
const const seenEncodedKeys: Set<
string | symbol
>
seenEncodedKeys = new var Set: SetConstructor
new <string | symbol>(iterable?: Iterable<string | symbol> | null | undefined) => Set<string | symbol> (+1 overload)
Set<string | symbol>()
for (const const k: string | symbolk of Reflect.function Reflect.ownKeys(target: object): (string | symbol)[]Returns the string and symbol keys of the own properties of an object. The own properties of an object
are those that are defined directly on that object, and are not inherited from the object's prototype.
ownKeys(self: S extends Constraint & { readonly fields: Struct.Fields; }self.fields: Struct.Fieldsfields)) {
const const encoded: toEncoded<Constraint>const encoded: {
Type: S["Encoded"];
Encoded: S["Encoded"];
DecodingServices: never;
EncodingServices: never;
Iso: S["Encoded"];
schema: S;
Rebuild: Rebuild;
ast: Ast;
annotate: (annotations: Annotations.Bottom<unknown, ReadonlyArray<Constraint>>) => toEncoded<Constraint>;
annotateKey: (annotations: Annotations.Key<unknown>) => toEncoded<Constraint>;
check: (checks_0: SchemaAST.Check<unknown>, ...checks: Array<SchemaAST.Check<unknown>>) => toEncoded<Constraint>;
rebuild: (ast: SchemaAST.AST) => toEncoded<Constraint>;
make: (input: unknown, options?: MakeOptions) => unknown;
makeOption: (input: unknown, options?: MakeOptions) => Option_.Option<unknown>;
makeEffect: (input: unknown, options?: MakeOptions) => Effect.Effect<unknown, SchemaError, never>;
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; <…;
}
encoded = const toEncoded: toEncodedLambda
;<Constraint>(self: Constraint) =>
toEncoded<Constraint>
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 Constraint & { readonly fields: Struct.Fields; }self.fields: Struct.Fieldsfields[const k: string | symbolk])
const const hasMapping: booleanhasMapping = var Object: ObjectConstructorProvides functionality common to all JavaScript objects.
Object.ObjectConstructor.hasOwn(o: object, v: PropertyKey): booleanDetermines whether an object has a property with the specified name.
hasOwn(mapping: const M extends { readonly [K in keyof S["fields"]]?: PropertyKey; }mapping, const k: string | symbolk)
const const encodedKey: PropertyKeyencodedKey = const hasMapping: booleanhasMapping ? (mapping: const M extends { readonly [K in keyof S["fields"]]?: PropertyKey; }mapping as any)[const k: string | symbolk] as type PropertyKey =
| string
| number
| symbol
PropertyKey : const k: string | symbolk
const const canonical: string | symbolcanonical = const canonicalPropertyKey: (
key: PropertyKey
) => string | symbol
canonicalPropertyKey(const encodedKey: PropertyKeyencodedKey)
if (const seenEncodedKeys: Set<
string | symbol
>
seenEncodedKeys.Set<string | symbol>.has(value: string | symbol): booleanhas(const canonical: string | symbolcanonical)) {
throw new module globalThisglobalThis.var Error: ErrorConstructor
new (message?: string, options?: globalThis.ErrorOptions) => globalThis.Error (+1 overload)
Error(`Duplicate encoded keys: ${import formatPropertyKeyformatPropertyKey(const encodedKey: PropertyKeyencodedKey)}`)
}
const seenEncodedKeys: Set<
string | symbol
>
seenEncodedKeys.Set<string | symbol>.add(value: string | symbol): Set<string | symbol>Appends a new element with a specified value to the end of the Set.
add(const canonical: string | symbolcanonical)
const fields: anyfields[const encodedKey: PropertyKeyencodedKey] = const encoded: toEncoded<Constraint>const encoded: {
Type: S["Encoded"];
Encoded: S["Encoded"];
DecodingServices: never;
EncodingServices: never;
Iso: S["Encoded"];
schema: S;
Rebuild: Rebuild;
ast: Ast;
annotate: (annotations: Annotations.Bottom<unknown, ReadonlyArray<Constraint>>) => toEncoded<Constraint>;
annotateKey: (annotations: Annotations.Key<unknown>) => toEncoded<Constraint>;
check: (checks_0: SchemaAST.Check<unknown>, ...checks: Array<SchemaAST.Check<unknown>>) => toEncoded<Constraint>;
rebuild: (ast: SchemaAST.AST) => toEncoded<Constraint>;
make: (input: unknown, options?: MakeOptions) => unknown;
makeOption: (input: unknown, options?: MakeOptions) => Option_.Option<unknown>;
makeEffect: (input: unknown, options?: MakeOptions) => Effect.Effect<unknown, SchemaError, never>;
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; <…;
}
encoded
if (const hasMapping: booleanhasMapping) {
const appliedMapping: anyappliedMapping[const k: string | symbolk] = const encodedKey: PropertyKeyencodedKey
const reverseMapping: anyreverseMapping[const encodedKey: PropertyKeyencodedKey] = const k: string | symbolk
}
}
return function Struct<
Fields extends Struct.Fields
>(fields: Fields): Struct<Fields>
Defines a struct schema from a map of field schemas.
Details
Each field value is a schema. Use
optionalKey
or
optional
to
mark fields as optional, and
mutableKey
to mark them as mutable.
The resulting schema's Type is a readonly object type with the fields'
decoded types. The Encoded form mirrors the field schemas' encoded types.
Example (Defining a basic struct)
import { Schema } from "effect"
const Person = Schema.Struct({
name: Schema.String,
age: Schema.Number,
email: Schema.optionalKey(Schema.String)
})
// { readonly name: string; readonly age: number; readonly email?: string }
type Person = typeof Person.Type
const alice = Schema.decodeUnknownSync(Person)({ name: "Alice", age: 30 })
console.log(alice)
// { name: 'Alice', age: 30 }
Struct(const fields: anyfields).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 Constraint & { readonly fields: Struct.Fields; }self,
import SchemaTransformationSchemaTransformation.function transform<T, E>(options: {
readonly decode: (input: E) => T
readonly encode: (input: T) => E
}): Transformation<T, E>
Creates a Transformation from pure (sync, infallible) decode and encode
functions.
When to use
Use when you need an infallible schema transformation that does not require
Effect services.
Details
- Each function receives the input and returns the output directly.
- Skips
None inputs (missing keys) — functions are only called on present values.
- Does not allocate Effects internally; uses optimized sync path.
Example (Converting between cents and dollars)
import { Schema, SchemaTransformation } from "effect"
const CentsFromDollars = Schema.Number.pipe(
Schema.decodeTo(
Schema.Number,
SchemaTransformation.transform({
decode: (dollars) => dollars * 100,
encode: (cents) => cents / 100
})
)
)
transform<any, any>({
decode: (input: any) => anydecode: import Struct_Struct_.const renameKeys: <any, any>(mapping: any) => (self: any) => {
[x: string]: any;
} (+1 overload)
renameKeys(const reverseMapping: anyreverseMapping),
encode: (input: any) => anyencode: import Struct_Struct_.const renameKeys: <any, any>(mapping: any) => (self: any) => {
[x: string]: any;
} (+1 overload)
renameKeys(const appliedMapping: anyappliedMapping)
})
)) as any
}
}