Skip to content

Class APIs

When working with schemas, you have a choice beyond the Schema.Struct constructor. You can leverage the power of classes through the Schema.Class utility, which comes with its own set of advantages tailored to common use cases:

Classes offer several features that simplify the schema creation process:

  • All-in-One Definition: With classes, you can define both a schema and an opaque type simultaneously.
  • Shared Functionality: You can incorporate shared functionality using class methods or getters.
  • Value Hashing and Equality: Utilize the built-in capability for checking value equality and applying hashing (thanks to Class implementing Data.Class).

To define a Class in @effect/schema, you need to provide:

  • The type of the class being created.
  • A unique identifier for the class.
  • The desired fields.

Example

1
import {
import Schema
Schema
} from "@effect/schema"
2
3
// Define your schema by providing the type, a unique identifier and the desired fields
4
class
class Person
Person
extends
import Schema
Schema
.
const Class: <Person>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: Schema.Annotations.Schema<Person, readonly []> | undefined) => Schema.Class<...>
Class
<
class Person
Person
>("Person")({
5
(property) id: typeof Schema.Number
id
:
import Schema
Schema
.
(alias) class Number export Number
Number
,
6
(property) name: typeof Schema.NonEmptyString
name
:
import Schema
Schema
.
class NonEmptyString
NonEmptyString
7
}) {}

In this setup, Person is a class where id is a number and name is a non-empty string. The constructor for the class creates instances with these specified properties.

1
import {
(method) Console.log(message?: any, ...optionalParams: any[]): void

Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args) for more information.

Sc
hema } from "@
(property) id: number
ef
fect/
(property) name: string
sche
ma"
2
3
class Person extends Schema.Class<Person>("Person")({
4
id: Schema.Number,
5
name: Schema.NonEmptyString
6
}) {}
7
8
namespace console var console: Console

The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```

// ---c
u
(method) Console.log(message?: any, ...optionalParams: any[]): void

Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args) for more information.

t--
-
9
console.log(new Person({ id: 1, name: "John" }))
10
/*
11
Output:
12
Person { id: 1, name: 'John' }
13
*/
14
15
// or
16
console.log(Person.make({ id: 1, name: "John" }))
17
/*
18
Output:
19
Person { id: 1, name: 'John' }
20
*/

If your schema does not require any fields, you can define a class with an empty object:

1
import {
import Schema
Schema
} from "@effect/schema"
2
3
class
class NoArgs
NoArgs
extends
import Schema
Schema
.
const Class: <NoArgs>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: Schema.Annotations.Schema<NoArgs, readonly []> | undefined) => Schema.Class<...>
Class
<
class NoArgs
NoArgs
>("NoArgs")({}) {}
4
5
const
const noargs1: NoArgs
noargs1
= new
constructor NoArgs(props: void | {}, options?: MakeOptions): NoArgs
NoArgs
()
6
// same as
7
const
const noargs2: NoArgs
noargs2
= new
constructor NoArgs(props: void | {}, options?: MakeOptions): NoArgs
NoArgs
({})

When you define a class using Schema.Class, the constructor automatically checks that the provided properties adhere to the schema’s rules. Here’s how you can define and instantiate a Person class:

1
import {
import Schema
Schema
} from "@effect/schema"
2
3
class
class Person
Person
extends
import Schema
Schema
.
const Class: <Person>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: Schema.Annotations.Schema<Person, readonly []> | undefined) => Schema.Class<...>
Class
<
class Person
Person
>("Person")({
4
(property) id: typeof Schema.Number
id
:
import Schema
Schema
.
(alias) class Number export Number
Number
,
5
(property) name: typeof Schema.NonEmptyString
name
:
import Schema
Schema
.
class NonEmptyString
NonEmptyString
6
}) {}
7
8
// ok
9
const
const john: Person
john
= new
constructor Person(props: { readonly id: number; readonly name: string; }, options?: MakeOptions): Person
Person
({
(property) id: number
id
: 1,
(property) name: string
name
: "John" })
10
11
const john: Person
john
.
(property) id: number
id
12
const john: Person
john
.
(property) name: string
name

This ensures that each property of the Person instance, like id and name, meets the conditions specified in the schema, such as id being a number and name being a non-empty string.

If an instance is created with invalid properties, the constructor throws an error detailing what went wrong:

1
import { Sche
(property) id: number
ma
} from "@effect/schema"
2
3
class Person extends Schema.Class<Person>("Person")({
4
id: Schema.Number,
5
name: Schema.NonEmptyString
6
}) {}
7
8
// ---cut---
9
new Person({ id: 1, name: "" }) // Attempting to instantiate with an invalid name
10
/*
11
throws:
12
ParseError: Person (Constructor)
13
└─ ["name"]
14
└─ a non empty string
15
└─ Predicate refinement failure
16
└─ Expected a non empty string, actual ""
17
*/

This error message clearly states that the name field failed the non-empty string predicate, providing precise feedback on why the validation failed.

There are scenarios where you might want to bypass validation during instantiation. Although not typically recommended, @effect/schema allows for this flexibility:

1
import { Schema } from "@effect/schema"
2
3
class Person extends Schema.Class<Person>("Person")({
4
id: Schema.Number,
5
na
constructor Person(props: { readonly id: number; readonly name: string; }, options?: MakeOptions): Person
me: Sc
hem
(property) id: number
a.
NonEm
(property) name: string
ptyS
tring
6
}) {}
7
8
// ---cut---
9
// Bypasses validation, thus avoiding errors
10
const john = new Person({ id: 1, name: "" }, true)
11
12
// or more explicitly
13
new Person({ id: 1, name: "" }, { disableValidation: true })

Thanks to the implementation of Data.Class, instances of your classes automatically support the Equal trait, which allows for easy comparison:

1
import {
import Schema
Schema
} from "@effect/schema"
2
import {
import Equal
Equal
} from "effect"
3
4
class
class Person
Person
extends
import Schema
Schema
.
const Class: <Person>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: Schema.Annotations.Schema<Person, readonly []> | undefined) => Schema.Class<...>
Class
<
class Person
Person
>("Person")({
5
(property) id: typeof Schema.Number
id
:
import Schema
Schema
.
(alias) class Number export Number
Number
,
6
(property) name: typeof Schema.NonEmptyString
name
:
import Schema
Schema
.
class NonEmptyString
NonEmptyString
7
}) {}
8
9
const
const john1: Person
john1
= new
constructor Person(props: { readonly id: number; readonly name: string; }, options?: MakeOptions): Person
Person
({
(property) id: number
id
: 1,
(property) name: string
name
: "John" })
10
const
const john2: Person
john2
= new
constructor Person(props: { readonly id: number; readonly name: string; }, options?: MakeOptions): Person
Person
({
(property) id: number
id
: 1,
(property) name: string
name
: "John" })
11
12
namespace console var console: Console

The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```

console
.
(method) Console.log(message?: any, ...optionalParams: any[]): void

Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args) for more information.

log
(
import Equal
Equal
.
function equals<Person, Person>(self: Person, that: Person): boolean (+1 overload)
equals
(
const john1: Person
john1
,
const john2: Person
john2
)) // Output: true

However, be aware that the Equal trait checks for equality only at the first level. If, for instance, a field is an array, the returned instances will not be considered equal:

1
import {
import Schema
Schema
} from "@effect/schema"
2
import {
import Equal
Equal
} from "effect"
3
4
class
class Person
Person
extends
import Schema
Schema
.
const Class: <Person>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: Schema.Annotations.Schema<Person, readonly []> | undefined) => Schema.Class<...>
Class
<
class Person
Person
>("Person")({
5
(property) id: typeof Schema.Number
id
:
import Schema
Schema
.
(alias) class Number export Number
Number
,
6
(property) name: typeof Schema.NonEmptyString
name
:
import Schema
Schema
.
class NonEmptyString
NonEmptyString
,
7
(property) hobbies: Schema.Array$<typeof Schema.String>
hobbies
:
import Schema
Schema
.
(alias) Array<typeof Schema.String>(value: typeof Schema.String): Schema.Array$<typeof Schema.String> export Array
Array
(
import Schema
Schema
.
(alias) class String export String
String
)
8
}) {}
9
10
const
const john1: Person
john1
= new
constructor Person(props: { readonly id: number; readonly name: string; readonly hobbies: readonly string[]; }, options?: MakeOptions): Person
Person
({
11
(property) id: number
id
: 1,
12
(property) name: string
name
: "John",
13
(property) hobbies: readonly string[]
hobbies
: ["reading", "coding"]
14
})
15
const
const john2: Person
john2
= new
constructor Person(props: { readonly id: number; readonly name: string; readonly hobbies: readonly string[]; }, options?: MakeOptions): Person
Person
({
16
(property) id: number
id
: 1,
17
(property) name: string
name
: "John",
18
(property) hobbies: readonly string[]
hobbies
: ["reading", "coding"]
19
})
20
21
namespace console var console: Console

The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```

console
.
(method) Console.log(message?: any, ...optionalParams: any[]): void

Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args) for more information.

log
(
import Equal
Equal
.
function equals<Person, Person>(self: Person, that: Person): boolean (+1 overload)
equals
(
const john1: Person
john1
,
const john2: Person
john2
)) // Output: false

To ensure deep equality for arrays, use Schema.Data combined with Data.array:

1
import {
import Schema
Schema
} from "@effect/schema"
2
import {
import Data
Data
,
import Equal
Equal
} from "effect"
3
4
class
class Person
Person
extends
import Schema
Schema
.
const Class: <Person>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: Schema.Annotations.Schema<Person, readonly []> | undefined) => Schema.Class<...>
Class
<
class Person
Person
>("Person")({
5
(property) id: typeof Schema.Number
id
:
import Schema
Schema
.
(alias) class Number export Number
Number
,
6
(property) name: typeof Schema.NonEmptyString
name
:
import Schema
Schema
.
class NonEmptyString
NonEmptyString
,
7
(property) hobbies: Schema.SchemaClass<readonly string[], readonly string[], never>
hobbies
:
import Schema
Schema
.
const Data: <never, readonly string[], readonly string[]>(item: Schema.Schema<readonly string[], readonly string[], never>) => Schema.SchemaClass<readonly string[], readonly string[], never>
Data
(
import Schema
Schema
.
(alias) Array<typeof Schema.String>(value: typeof Schema.String): Schema.Array$<typeof Schema.String> export Array
Array
(
import Schema
Schema
.
(alias) class String export String
String
))
8
}) {}
9
10
const
const john1: Person
john1
= new
constructor Person(props: { readonly id: number; readonly name: string; readonly hobbies: readonly string[]; }, options?: MakeOptions): Person
Person
({
11
(property) id: number
id
: 1,
12
(property) name: string
name
: "John",
13
(property) hobbies: readonly string[]
hobbies
:
import Data
Data
.
const array: <string[]>(as: string[]) => readonly string[]
array
(["reading", "coding"])
14
})
15
const
const john2: Person
john2
= new
constructor Person(props: { readonly id: number; readonly name: string; readonly hobbies: readonly string[]; }, options?: MakeOptions): Person
Person
({
16
(property) id: number
id
: 1,
17
(property) name: string
name
: "John",
18
(property) hobbies: readonly string[]
hobbies
:
import Data
Data
.
const array: <string[]>(as: string[]) => readonly string[]
array
(["reading", "coding"])
19
})
20
21
namespace console var console: Console

The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```

console
.
(method) Console.log(message?: any, ...optionalParams: any[]): void

Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args) for more information.

log
(
import Equal
Equal
.
function equals<Person, Person>(self: Person, that: Person): boolean (+1 overload)
equals
(
const john1: Person
john1
,
const john2: Person
john2
)) // Output: true

You have the flexibility to enhance schema classes with custom getters and methods.

Example

1
import {
import Schema
Schema
} from "@effect/schema"
2
3
class
class Person
Person
extends
import Schema
Schema
.
const Class: <Person>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: Schema.Annotations.Schema<Person, readonly []> | undefined) => Schema.Class<...>
Class
<
class Person
Person
>("Person")({
4
(property) id: typeof Schema.Number
id
:
import Schema
Schema
.
(alias) class Number export Number
Number
,
5
(property) name: typeof Schema.NonEmptyString
name
:
import Schema
Schema
.
class NonEmptyString
NonEmptyString
6
}) {
7
// Custom getter to return the name in uppercase
8
get
(getter) Person.upperName: string
upperName
() {
9
return this.
(property) name: string
name
.
(method) String.toUpperCase(): string

Converts all the alphabetic characters in a string to uppercase.

toUpperCase
()
10
}
11
}
12
13
const
const john: Person
john
= new
constructor Person(props: { readonly id: number; readonly name: string; }, options?: MakeOptions): Person
Person
({
(property) id: number
id
: 1,
(property) name: string
name
: "John" })
14
15
namespace console var console: Console

The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```

console
.
(method) Console.log(message?: any, ...optionalParams: any[]): void

Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args) for more information.

log
(
const john: Person
john
.
(property) Person.upperName: string
upperName
) // Output: "JOHN"

When you define a class using Schema.Class, it not only creates a new class but also treats this class as a schema. This means the class can be utilized wherever a schema is expected.

1
import {
import Schema
Schema
} from "@effect/schema"
2
3
class
class Person
Person
extends
import Schema
Schema
.
const Class: <Person>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: Schema.Annotations.Schema<Person, readonly []> | undefined) => Schema.Class<...>
Class
<
class Person
Person
>("Person")({
4
(property) id: typeof Schema.Number
id
:
import Schema
Schema
.
(alias) class Number export Number
Number
,
5
(property) name: typeof Schema.NonEmptyString
name
:
import Schema
Schema
.
class NonEmptyString
NonEmptyString
6
}) {}
7
8
// Person can be used as a normal schema
9
const
const Persons: Schema.Array$<typeof Person>
Persons
=
import Schema
Schema
.
(alias) Array<typeof Person>(value: typeof Person): Schema.Array$<typeof Person> export Array
Array
(
class Person
Person
)

The class also includes a fields static property, which outlines the fields defined during the class creation.

1
import {
import Schema
Schema
} from "@effect/schema"
2
3
class
class Person
Person
extends
import Schema
Schema
.
const Class: <Person>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: Schema.Annotations.Schema<Person, readonly []> | undefined) => Schema.Class<...>
Class
<
class Person
Person
>("Person")({
4
(property) id: typeof Schema.Number
id
:
import Schema
Schema
.
(alias) class Number export Number
Number
,
5
(property) name: typeof Schema.NonEmptyString
name
:
import Schema
Schema
.
class NonEmptyString
NonEmptyString
6
}) {}
7
8
class Person
Person
.
(property) Class<Person, { id: typeof Number$; name: typeof NonEmptyString; }, Struct<Fields extends Struct.Fields>.Encoded<{ id: typeof Number$; name: typeof NonEmptyString; }>, never, { ...; } & { ...; }, {}, {}>.fields: { readonly id: typeof Schema.Number; readonly name: typeof Schema.NonEmptyString; }
fields

A class that extends Schema.Class implicitly forms a schema transformation from a structured type to a class type. For instance, consider the following definition:

1
import {
import Schema
Schema
} from "@effect/schema"
2
3
class
class Person
Person
extends
import Schema
Schema
.
const Class: <Person>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: Schema.Annotations.Schema<Person, readonly []> | undefined) => Schema.Class<...>
Class
<
class Person
Person
>("Person")({
4
(property) id: typeof Schema.Number
id
:
import Schema
Schema
.
(alias) class Number export Number
Number
,
5
(property) name: typeof Schema.NonEmptyString
name
:
import Schema
Schema
.
class NonEmptyString
NonEmptyString
6
}) {}

This class definition serves as a transformation from the following struct schema:

1
Schema.Struct({
2
id: Schema.Number,
3
name: Schema.NonEmptyString
4
})

to a schema that represents the Person class.

There are two primary ways to add annotations depending on your requirements:

  1. Adding Annotations to the Struct Schema (the “from” part of the transformation):

    You can annotate the struct schema component, which is transformed into the class.

    1
    import {
    import Schema
    Schema
    } from "@effect/schema"
    2
    3
    class
    class Person
    Person
    extends
    import Schema
    Schema
    .
    const Class: <Person>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: Schema.Annotations.Schema<Person, readonly []> | undefined) => Schema.Class<...>
    Class
    <
    class Person
    Person
    >("Person")(
    4
    import Schema
    Schema
    .
    function Struct<{ id: typeof Schema.Number; name: typeof Schema.NonEmptyString; }>(fields: { id: typeof Schema.Number; name: typeof Schema.NonEmptyString; }): Schema.Struct<{ id: typeof Schema.Number; name: typeof Schema.NonEmptyString; }> (+1 overload) namespace Struct
    Struct
    ({
    5
    (property) id: typeof Schema.Number
    id
    :
    import Schema
    Schema
    .
    (alias) class Number export Number
    Number
    ,
    6
    (property) name: typeof Schema.NonEmptyString
    name
    :
    import Schema
    Schema
    .
    class NonEmptyString
    NonEmptyString
    7
    }).
    (method) Struct<{ id: typeof Number$; name: typeof NonEmptyString; }>.annotations(annotations: Schema.Annotations.Schema<{ readonly id: number; readonly name: string; }, readonly []>): Schema.Struct<{ id: typeof Schema.Number; name: typeof Schema.NonEmptyString; }>

    Merges a set of new annotations with existing ones, potentially overwriting any duplicates.

    annotations
    ({
    (property) Annotations.Schema<A, TypeParameters extends ReadonlyArray<any> = readonly []>.identifier?: string
    identifier
    : "From" })
    8
    ) {}
    9
    10
    namespace console var console: Console

    The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```

    console
    .
    (method) Console.log(message?: any, ...optionalParams: any[]): void

    Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args) for more information.

    log
    (
    var String: StringConstructor (value?: any) => string

    Allows manipulation and formatting of text strings and determination and location of substrings within strings.

    String
    (
    class Person
    Person
    .
    (property) Class<Person, { id: typeof Number$; name: typeof NonEmptyString; }, Struct<Fields extends Struct.Fields>.Encoded<{ id: typeof Number$; name: typeof NonEmptyString; }>, never, { ...; } & { ...; }, {}, {}>.ast: Transformation
    ast
    )) // Output: (From <-> Person)
  2. Adding Annotations to the Class Schema (the “to” part of the transformation):

    Alternatively, annotations can be added directly to the class schema, affecting how the class is represented as a schema.

    1
    import {
    import Schema
    Schema
    } from "@effect/schema"
    2
    3
    class
    class Person
    Person
    extends
    import Schema
    Schema
    .
    const Class: <Person>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: Schema.Annotations.Schema<Person, readonly []> | undefined) => Schema.Class<...>
    Class
    <
    class Person
    Person
    >("Person")(
    4
    {
    5
    (property) id: typeof Schema.Number
    id
    :
    import Schema
    Schema
    .
    (alias) class Number export Number
    Number
    ,
    6
    (property) name: typeof Schema.NonEmptyString
    name
    :
    import Schema
    Schema
    .
    class NonEmptyString
    NonEmptyString
    7
    },
    8
    {
    (property) Annotations.Schema<A, TypeParameters extends ReadonlyArray<any> = readonly []>.identifier?: string
    identifier
    : "To" }
    9
    ) {}
    10
    11
    namespace console var console: Console

    The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```

    console
    .
    (method) Console.log(message?: any, ...optionalParams: any[]): void

    Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args) for more information.

    log
    (
    var String: StringConstructor (value?: any) => string

    Allows manipulation and formatting of text strings and determination and location of substrings within strings.

    String
    (
    class Person
    Person
    .
    (property) Class<Person, { id: typeof Number$; name: typeof NonEmptyString; }, Struct<Fields extends Struct.Fields>.Encoded<{ id: typeof Number$; name: typeof NonEmptyString; }>, never, { ...; } & { ...; }, {}, {}>.ast: Transformation
    ast
    )) // Output: (Person (Encoded side) <-> To)

The Schema.suspend combinator is useful when you need to define a schema that depends on itself, like in the case of recursive data structures. In this example, the Category schema depends on itself because it has a field subcategories that is an array of Category objects.

1
import {
import Schema
Schema
} from "@effect/schema"
2
3
class
class Category
Category
extends
import Schema
Schema
.
const Class: <Category>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: Schema.Annotations.Schema<Category, readonly []> | undefined) => Schema.Class<...>
Class
<
class Category
Category
>("Category")({
4
(property) name: typeof Schema.String
name
:
import Schema
Schema
.
(alias) class String export String
String
,
5
(property) subcategories: Schema.Array$<Schema.suspend<Category, Category, never>>
subcategories
:
import Schema
Schema
.
(alias) Array<Schema.suspend<Category, Category, never>>(value: Schema.suspend<Category, Category, never>): Schema.Array$<Schema.suspend<Category, Category, never>> export Array
Array
(
6
import Schema
Schema
.
const suspend: <Category, Category, never>(f: () => Schema.Schema<Category, Category, never>) => Schema.suspend<Category, Category, never>
suspend
(():
import Schema
Schema
.
interface Schema<in out A, in out I = A, out R = never> namespace Schema
Schema
<
class Category
Category
> =>
class Category
Category
)
7
)
8
}) {}
1
import {
import Schema
Schema
} from "@effect/schema"
2
3
// @ts-expect-error
4
class
class Category
Category
extends
import Schema
Schema
.
const Class: <Category>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: Schema.Annotations.Schema<Category, readonly []> | undefined) => Schema.Class<...>
Class
<
class Category
Category
>("Category")({
5
(property) name: typeof Schema.String
name
:
import Schema
Schema
.
(alias) class String export String
String
,
6
// @ts-expect-error
7
(property) subcategories: Schema.Array$<Schema.suspend<unknown, unknown, unknown>>
subcategories
:
import Schema
Schema
.
(alias) Array<Schema.suspend<unknown, unknown, unknown>>(value: Schema.suspend<unknown, unknown, unknown>): Schema.Array$<Schema.suspend<unknown, unknown, unknown>> export Array
Array
(
import Schema
Schema
.
const suspend: <unknown, unknown, unknown>(f: () => Schema.Schema<unknown, unknown, unknown>) => Schema.suspend<unknown, unknown, unknown>
suspend
(() =>
class Category
Category
))
8
}) {}
9
/*
10
'Category' is referenced directly or indirectly in its own base expression.ts(2506)
11
*/

Here’s an example of two mutually recursive schemas, Expression and Operation, that represent a simple arithmetic expression tree.

1
import {
import Schema
Schema
} from "@effect/schema"
2
3
class
class Expression
Expression
extends
import Schema
Schema
.
const Class: <Expression>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: Schema.Annotations.Schema<Expression, readonly []> | undefined) => Schema.Class<...>
Class
<
class Expression
Expression
>("Expression")({
4
(property) type: Schema.Literal<["expression"]>
type
:
import Schema
Schema
.
function Literal<["expression"]>(literals_0: "expression"): Schema.Literal<["expression"]> (+2 overloads)
Literal
("expression"),
5
(property) value: Schema.Union<[typeof Schema.Number, Schema.suspend<Operation, Operation, never>]>
value
:
import Schema
Schema
.
function Union<[typeof Schema.Number, Schema.suspend<Operation, Operation, never>]>(members_0: typeof Schema.Number, members_1: Schema.suspend<Operation, Operation, never>): Schema.Union<...> (+3 overloads)
Union
(
6
import Schema
Schema
.
(alias) class Number export Number
Number
,
7
import Schema
Schema
.
const suspend: <Operation, Operation, never>(f: () => Schema.Schema<Operation, Operation, never>) => Schema.suspend<Operation, Operation, never>
suspend
(():
import Schema
Schema
.
interface Schema<in out A, in out I = A, out R = never> namespace Schema
Schema
<
class Operation
Operation
> =>
class Operation
Operation
)
8
)
9
}) {}
10
11
class
class Operation
Operation
extends
import Schema
Schema
.
const Class: <Operation>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: Schema.Annotations.Schema<Operation, readonly []> | undefined) => Schema.Class<...>
Class
<
class Operation
Operation
>("Operation")({
12
(property) type: Schema.Literal<["operation"]>
type
:
import Schema
Schema
.
function Literal<["operation"]>(literals_0: "operation"): Schema.Literal<["operation"]> (+2 overloads)
Literal
("operation"),
13
(property) operator: Schema.Literal<["+", "-"]>
operator
:
import Schema
Schema
.
function Literal<["+", "-"]>(literals_0: "+", literals_1: "-"): Schema.Literal<["+", "-"]> (+2 overloads)
Literal
("+", "-"),
14
(property) left: typeof Expression
left
:
class Expression
Expression
,
15
(property) right: typeof Expression
right
:
class Expression
Expression
16
}) {}

Defining a recursive schema where the Encoded type differs from the Type type adds another layer of complexity. In such cases, we need to define an interface for the Encoded type.

Let’s consider an example: suppose we want to add an id field to the Category schema, where the schema for id is NumberFromString. It’s important to note that NumberFromString is a schema that transforms a string into a number, so the Type and Encoded types of NumberFromString differ, being number and string respectively. When we add this field to the Category schema, TypeScript raises an error:

1
import {
import Schema
Schema
} from "@effect/schema"
2
3
class
class Category
Category
extends
import Schema
Schema
.
const Class: <Category>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: Schema.Annotations.Schema<Category, readonly []> | undefined) => Schema.Class<...>
Class
<
class Category
Category
>("Category")({
4
(property) id: typeof Schema.NumberFromString
id
:
import Schema
Schema
.
class NumberFromString

This schema transforms a `string` into a `number` by parsing the string using the `parse` function of the `effect/Number` module. It returns an error if the value can't be converted (for example when non-numeric characters are provided). The following special string values are supported: "NaN", "Infinity", "-Infinity".

NumberFromString
,
5
(property) name: typeof Schema.String
name
:
import Schema
Schema
.
(alias) class String export String
String
,
6
(property) subcategories: Schema.Array$<Schema.suspend<Category, Category, never>>
subcategories
:
import Schema
Schema
.
(alias) Array<Schema.suspend<Category, Category, never>>(value: Schema.suspend<Category, Category, never>): Schema.Array$<Schema.suspend<Category, Category, never>> export Array
Array
(
7
// @ts-expect-error
8
import Schema
Schema
.
const suspend: <Category, Category, never>(f: () => Schema.Schema<Category, Category, never>) => Schema.suspend<Category, Category, never>
suspend
(():
import Schema
Schema
.
interface Schema<in out A, in out I = A, out R = never> namespace Schema
Schema
<
class Category
Category
> =>
class Category
Category
)
9
)
10
}) {}
11
/*
12
Type 'typeof Category' is not assignable to type 'Schema<Category, Category, never>'.
13
The types of 'Encoded.id' are incompatible between these types.
14
Type 'string' is not assignable to type 'number'.ts(2322)
15
*/

This error occurs because the explicit annotation S.suspend((): S.Schema<Category> => Category is no longer sufficient and needs to be adjusted by explicitly adding the Encoded type:

1
import {
import Schema
Schema
} from "@effect/schema"
2
3
interface
interface CategoryEncoded
CategoryEncoded
{
4
readonly
(property) CategoryEncoded.id: string
id
: string
5
readonly
(property) CategoryEncoded.name: string
name
: string
6
readonly
(property) CategoryEncoded.subcategories: readonly CategoryEncoded[]
subcategories
:
interface ReadonlyArray<T>
ReadonlyArray
<
interface CategoryEncoded
CategoryEncoded
>
7
}
8
9
class
class Category
Category
extends
import Schema
Schema
.
const Class: <Category>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: Schema.Annotations.Schema<Category, readonly []> | undefined) => Schema.Class<...>
Class
<
class Category
Category
>("Category")({
10
(property) id: typeof Schema.NumberFromString
id
:
import Schema
Schema
.
class NumberFromString

This schema transforms a `string` into a `number` by parsing the string using the `parse` function of the `effect/Number` module. It returns an error if the value can't be converted (for example when non-numeric characters are provided). The following special string values are supported: "NaN", "Infinity", "-Infinity".

NumberFromString
,
11
(property) name: typeof Schema.String
name
:
import Schema
Schema
.
(alias) class String export String
String
,
12
(property) subcategories: Schema.Array$<Schema.suspend<Category, CategoryEncoded, never>>
subcategories
:
import Schema
Schema
.
(alias) Array<Schema.suspend<Category, CategoryEncoded, never>>(value: Schema.suspend<Category, CategoryEncoded, never>): Schema.Array$<...> export Array
Array
(
13
import Schema
Schema
.
const suspend: <Category, CategoryEncoded, never>(f: () => Schema.Schema<Category, CategoryEncoded, never>) => Schema.suspend<Category, CategoryEncoded, never>
suspend
(
14
():
import Schema
Schema
.
interface Schema<in out A, in out I = A, out R = never> namespace Schema
Schema
<
class Category
Category
,
interface CategoryEncoded
CategoryEncoded
> =>
class Category
Category
15
)
16
)
17
}) {}

As we’ve observed, it’s necessary to define an interface for the Encoded of the schema to enable recursive schema definition, which can complicate things and be quite tedious. One pattern to mitigate this is to separate the field responsible for recursion from all other fields.

1
import {
import Schema
Schema
} from "@effect/schema"
2
3
const
const fields: { id: typeof Schema.NumberFromString; name: typeof Schema.String; }
fields
= {
4
(property) id: typeof Schema.NumberFromString
id
:
import Schema
Schema
.
class NumberFromString

This schema transforms a `string` into a `number` by parsing the string using the `parse` function of the `effect/Number` module. It returns an error if the value can't be converted (for example when non-numeric characters are provided). The following special string values are supported: "NaN", "Infinity", "-Infinity".

NumberFromString
,
5
(property) name: typeof Schema.String
name
:
import Schema
Schema
.
(alias) class String export String
String
6
// ...possibly other fields
7
}
8
9
interface
interface CategoryEncoded
CategoryEncoded
extends
import Schema
Schema
.
namespace Struct
Struct
.
type Struct<Fields extends Struct.Fields>.Encoded<F extends Schema.Struct.Fields> = { readonly [K in Exclude<keyof F, Schema.Struct.EncodedTokenKeys<F>> as Schema.Struct.Key<F, K>]: Schema.Schema.Encoded<F[K]>; } & { readonly [K in Schema.Struct.EncodedTokenKeys<...> as Schema.Struct.Key<...>]?: Schema.Schema.Encoded<...>; }
Encoded
<typeof
const fields: { id: typeof Schema.NumberFromString; name: typeof Schema.String; }
fields
> {
10
// Define `subcategories` using recursion
11
readonly
(property) CategoryEncoded.subcategories: readonly CategoryEncoded[]
subcategories
:
interface ReadonlyArray<T>
ReadonlyArray
<
interface CategoryEncoded
CategoryEncoded
>
12
}
13
14
class
class Category
Category
extends
import Schema
Schema
.
const Class: <Category>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: Schema.Annotations.Schema<Category, readonly []> | undefined) => Schema.Class<...>
Class
<
class Category
Category
>("Category")({
15
...
const fields: { id: typeof Schema.NumberFromString; name: typeof Schema.String; }
fields
, // Include the fields
16
(property) subcategories: Schema.Array$<Schema.suspend<Category, CategoryEncoded, never>>
subcategories
:
import Schema
Schema
.
(alias) Array<Schema.suspend<Category, CategoryEncoded, never>>(value: Schema.suspend<Category, CategoryEncoded, never>): Schema.Array$<...> export Array
Array
(
17
// Define `subcategories` using recursion
18
import Schema
Schema
.
const suspend: <Category, CategoryEncoded, never>(f: () => Schema.Schema<Category, CategoryEncoded, never>) => Schema.suspend<Category, CategoryEncoded, never>
suspend
(
19
():
import Schema
Schema
.
interface Schema<in out A, in out I = A, out R = never> namespace Schema
Schema
<
class Category
Category
,
interface CategoryEncoded
CategoryEncoded
> =>
class Category
Category
20
)
21
)
22
}) {}

You can also create classes that extend TaggedClass and TaggedError from the effect/Data module.

Example

1
import {
import Schema
Schema
} from "@effect/schema"
2
3
class
class TaggedPerson
TaggedPerson
extends
import Schema
Schema
.
const TaggedClass: <TaggedPerson>(identifier?: string) => <Tag, Fields>(tag: Tag, fieldsOr: Fields | HasFields<Fields>, annotations?: Schema.Annotations.Schema<TaggedPerson, readonly []> | undefined) => Schema.TaggedClass<...>
TaggedClass
<
class TaggedPerson
TaggedPerson
>()(
4
"TaggedPerson",
5
{
6
(property) name: typeof Schema.String
name
:
import Schema
Schema
.
(alias) class String export String
String
7
}
8
) {}
9
10
class
class HttpError
HttpError
extends
import Schema
Schema
.
const TaggedError: <HttpError>(identifier?: string) => <Tag, Fields>(tag: Tag, fieldsOr: Fields | HasFields<Fields>, annotations?: Schema.Annotations.Schema<HttpError, readonly []> | undefined) => Schema.TaggedErrorClass<...>
TaggedError
<
class HttpError
HttpError
>()("HttpError", {
11
(property) status: typeof Schema.Number
status
:
import Schema
Schema
.
(alias) class Number export Number
Number
12
}) {}
13
14
const
const joe: TaggedPerson
joe
= new
constructor TaggedPerson(props: { readonly name: string; }, options?: MakeOptions): TaggedPerson
TaggedPerson
({
(property) name: string
name
: "Joe" })
15
namespace console var console: Console

The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```

console
.
(method) Console.log(message?: any, ...optionalParams: any[]): void

Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args) for more information.

log
(
const joe: TaggedPerson
joe
.
(property) _tag: "TaggedPerson"
_tag
) // "TaggedPerson"
16
17
const
const error: HttpError
error
= new
constructor HttpError(props: { readonly status: number; }, options?: MakeOptions): HttpError
HttpError
({
(property) status: number
status
: 404 })
18
namespace console var console: Console

The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```

console
.
(method) Console.log(message?: any, ...optionalParams: any[]): void

Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args) for more information.

log
(
const error: HttpError
error
.
(property) _tag: "HttpError"
_tag
) // "HttpError"
19
namespace console var console: Console

The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```

console
.
(method) Console.log(message?: any, ...optionalParams: any[]): void

Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args) for more information.

log
(
const error: HttpError
error
.
(property) stack?: string | undefined
stack
) // access the stack trace

In situations where you need to augment your existing class with more fields, the built-in extend static utility comes in handy.

Example

1
import {
import Schema
Schema
} from "@effect/schema"
2
3
class
class Person
Person
extends
import Schema
Schema
.
const Class: <Person>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: Schema.Annotations.Schema<Person, readonly []> | undefined) => Schema.Class<...>
Class
<
class Person
Person
>("Person")({
4
(property) id: typeof Schema.Number
id
:
import Schema
Schema
.
(alias) class Number export Number
Number
,
5
(property) name: typeof Schema.NonEmptyString
name
:
import Schema
Schema
.
class NonEmptyString
NonEmptyString
6
}) {
7
get
(getter) Person.upperName: string
upperName
() {
8
return this.
(property) name: string
name
.
(method) String.toUpperCase(): string

Converts all the alphabetic characters in a string to uppercase.

toUpperCase
()
9
}
10
}
11
12
class
class PersonWithAge
PersonWithAge
extends
class Person
Person
.
(method) Class<Person, { id: typeof Number$; name: typeof NonEmptyString; }, Struct<Fields extends Struct.Fields>.Encoded<{ id: typeof Number$; name: typeof NonEmptyString; }>, never, { ...; } & { ...; }, {}, {}>.extend<PersonWithAge>(identifier: string): <newFields>(fields: newFields | HasFields<newFields>, annotations?: Schema.Annotations.Schema<PersonWithAge, readonly []> | undefined) => Schema.Class<...>
extend
<
class PersonWithAge
PersonWithAge
>("PersonWithAge")(
13
{
14
(property) age: typeof Schema.Number
age
:
import Schema
Schema
.
(alias) class Number export Number
Number
15
}
16
) {
17
get
(getter) PersonWithAge.isAdult: boolean
isAdult
() {
18
return this.
(property) age: number
age
>= 18
19
}
20
}

You have the option to enhance a class with (effectful) transformations. This becomes valuable when you want to enrich or validate an entity sourced from a data store.

1
import {
import Schema
Schema
,
import ParseResult
ParseResult
} from "@effect/schema"
2
import {
import Effect
Effect
,
import Option
Option
} from "effect"
3
4
export class
class Person
Person
extends
import Schema
Schema
.
const Class: <Person>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: Schema.Annotations.Schema<Person, readonly []> | undefined) => Schema.Class<...>
Class
<
class Person
Person
>("Person")({
5
(property) id: typeof Schema.Number
id
:
import Schema
Schema
.
(alias) class Number export Number
Number
,
6
(property) name: typeof Schema.String
name
:
import Schema
Schema
.
(alias) class String export String
String
7
}) {}
8
9
namespace console var console: Console

The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```

console
.
(method) Console.log(message?: any, ...optionalParams: any[]): void

Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args) for more information.

log
(
import Schema
Schema
.
(alias) decodeUnknownSync<Person, { readonly id: number; readonly name: string; }>(schema: Schema.Schema<Person, { readonly id: number; readonly name: string; }, never>, options?: ParseOptions): (u: unknown, overrideOptions?: ParseOptions) => Person export decodeUnknownSync
decodeUnknownSync
(
class Person
Person
)({
(property) id: number
id
: 1,
(property) name: string
name
: "name" }))
10
/*
11
Output:
12
Person { id: 1, name: 'name' }
13
*/
14
15
function
function getAge(id: number): Effect.Effect<number, Error>
getAge
(
(parameter) id: number
id
: number):
import Effect
Effect
.
interface Effect<out A, out E = never, out R = never> namespace Effect

The `Effect` interface defines a value that lazily describes a workflow or job. The workflow requires some context `R`, and may fail with an error of type `E`, or succeed with a value of type `A`. `Effect` values model resourceful interaction with the outside world, including synchronous, asynchronous, concurrent, and parallel interaction. They use a fiber-based concurrency model, with built-in support for scheduling, fine-grained interruption, structured concurrency, and high scalability. To run an `Effect` value, you need a `Runtime`, which is a type that is capable of executing `Effect` values.

Effect
<number,
interface Error
Error
> {
16
return
import Effect
Effect
.
const succeed: <number>(value: number) => Effect.Effect<number, never, never>
succeed
(
(parameter) id: number
id
+ 2)
17
}
18
19
export class
class PersonWithTransform
PersonWithTransform
extends
class Person
Person
.
(method) Class<Person, { id: typeof Number$; name: typeof String$; }, Struct<Fields extends Struct.Fields>.Encoded<{ id: typeof Number$; name: typeof String$; }>, never, { ...; } & { ...; }, {}, {}>.transformOrFail<PersonWithTransform>(identifier: string): <newFields, R2, R3>(fields: newFields, options: { readonly decode: (input: { readonly id: number; readonly name: string; }, options: ParseOptions, ast: Transformation) => Effect.Effect<...>; readonly encode: (input: { [K in keyof Schema.Struct<Fields extends Schema.Struct.Fields>.Type<...>]: Schema.Struct.Type<...>[K]; }, options: ParseOptions, ast: Transformation) => Effect.Effect<...>; }, annotations?: Schema.Annotations.Schema<...> | undefined) => Schema.Class<...>
transformOrFail
<
class PersonWithTransform
PersonWithTransform
>(
20
"PersonWithTransform"
21
)(
22
{
23
(property) age: Schema.optionalWith<typeof Schema.Number, { exact: true; as: "Option"; }>
age
:
import Schema
Schema
.
const optionalWith: <typeof Schema.Number, { exact: true; as: "Option"; }>(self: typeof Schema.Number, options: { exact: true; as: "Option"; }) => Schema.optionalWith<typeof Schema.Number, { exact: true; as: "Option"; }> (+1 overload)
optionalWith
(
import Schema
Schema
.
(alias) class Number export Number
Number
, {
(property) exact: true
exact
: true,
(property) as: "Option"
as
: "Option" })
24
},
25
{
26
(property) decode: (input: { readonly id: number; readonly name: string; }, options: ParseOptions, ast: Transformation) => Effect.Effect<{ readonly id: number; readonly name: string; readonly age: Option.Option<...>; }, ParseResult.ParseIssue, never>
decode
: (
(parameter) input: { readonly id: number; readonly name: string; }
input
) =>
27
import Effect
Effect
.
const mapBoth: <number, Error, never, ParseResult.Type, { age: Option.Option<number>; id: number; name: string; }>(self: Effect.Effect<number, Error, never>, options: { ...; }) => Effect.Effect<...> (+1 overload)

Returns an effect whose failure and success channels have been mapped by the specified `onFailure` and `onSuccess` functions.

mapBoth
(
function getAge(id: number): Effect.Effect<number, Error>
getAge
(
(parameter) input: { readonly id: number; readonly name: string; }
input
.
(property) id: number
id
), {
28
(property) onFailure: (e: Error) => ParseResult.Type
onFailure
: (
(parameter) e: Error
e
) =>
29
new
import ParseResult
ParseResult
.
constructor Type(ast: AST, actual: unknown, message?: string | undefined): ParseResult.Type

The `Type` variant of the `ParseIssue` type represents an error that occurs when the `actual` value is not of the expected type. The `ast` field specifies the expected type, and the `actual` field contains the value that caused the error.

Type
(
import Schema
Schema
.
(alias) class String export String
String
.
(property) Schema<in out A, in out I = A, out R = never>.ast: AST
ast
,
(parameter) input: { readonly id: number; readonly name: string; }
input
.
(property) id: number
id
,
(parameter) e: Error
e
.
(property) Error.message: string
message
),
30
// must return { age: Option<number> }
31
(property) onSuccess: (a: number) => { age: Option.Option<number>; id: number; name: string; }
onSuccess
: (
(parameter) age: number
age
) => ({ ...
(parameter) input: { readonly id: number; readonly name: string; }
input
,
(property) age: Option.Option<number>
age
:
import Option
Option
.
const some: <number>(value: number) => Option.Option<number>

Creates a new `Option` that wraps the given value.

some
(
(parameter) age: number
age
) })
32
}),
33
(property) encode: (input: { readonly id: number; readonly name: string; readonly age: Option.Option<number>; }, options: ParseOptions, ast: Transformation) => Effect.Effect<...>
encode
:
import ParseResult
ParseResult
.
const succeed: <A>(a: A) => Either<A, ParseResult.ParseIssue>
succeed
34
}
35
) {}
36
37
import Schema
Schema
.
const decodeUnknownPromise: <PersonWithTransform, { readonly id: number; readonly name: string; }>(schema: Schema.Schema<PersonWithTransform, { readonly id: number; readonly name: string; }, never>, options?: ParseOptions) => (u: unknown, overrideOptions?: ParseOptions) => Promise<...>
decodeUnknownPromise
(
class PersonWithTransform
PersonWithTransform
)({
38
(property) id: number
id
: 1,
39
(property) name: string
name
: "name"
40
}).
(method) Promise<PersonWithTransform>.then<void, never>(onfulfilled?: ((value: PersonWithTransform) => void | PromiseLike<void>) | null | undefined, onrejected?: ((reason: any) => PromiseLike<never>) | null | undefined): Promise<...>

Attaches callbacks for the resolution and/or rejection of the Promise.

then
(
namespace console var console: Console

The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```

console
.
(method) Console.log(message?: any, ...optionalParams: any[]): void

Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args) for more information.

log
)
41
/*
42
Output:
43
PersonWithTransform {
44
id: 1,
45
name: 'name',
46
age: { _id: 'Option', _tag: 'Some', value: 3 }
47
}
48
*/
49
50
export class
class PersonWithTransformFrom
PersonWithTransformFrom
extends
class Person
Person
.
(method) Class<Person, { id: typeof Number$; name: typeof String$; }, Struct<Fields extends Struct.Fields>.Encoded<{ id: typeof Number$; name: typeof String$; }>, never, { ...; } & { ...; }, {}, {}>.transformOrFailFrom<PersonWithTransformFrom>(identifier: string): <newFields, R2, R3>(fields: newFields, options: { readonly decode: (input: { readonly id: number; readonly name: string; }, options: ParseOptions, ast: Transformation) => Effect.Effect<...>; readonly encode: (input: { [K in keyof ({ ...; } & ... 2 more ... & { readonly [K in Schema.Struct<Fields extends Schema.Struct.Fields>.EncodedTokenKeys<...> as Schema.Struct.Key<...>]?: Schema.Schema<in out A, in out I = A, out R = never>.Encoded<...>; })]: ({ ...; } & ... 2 more ... & { readonly [K in Schema.Struct<Fields extends Schema.Struct.Fields>.EncodedTokenKeys<...> as Schema.Struct.Key<...>]?: Schema.Schema<in out A, in out I = A, out R = never>.Encoded<...>; })[K]; }, options: ParseOptions, ast: Transformation) => Effect.Effect<...>; }, annotations?: Schema.Annotations.Schema<...> | undefined) => Schema.Class<...>
transformOrFailFrom
<
class PersonWithTransformFrom
PersonWithTransformFrom
>(
51
"PersonWithTransformFrom"
52
)(
53
{
54
(property) age: Schema.optionalWith<typeof Schema.Number, { exact: true; as: "Option"; }>
age
:
import Schema
Schema
.
const optionalWith: <typeof Schema.Number, { exact: true; as: "Option"; }>(self: typeof Schema.Number, options: { exact: true; as: "Option"; }) => Schema.optionalWith<typeof Schema.Number, { exact: true; as: "Option"; }> (+1 overload)
optionalWith
(
import Schema
Schema
.
(alias) class Number export Number
Number
, {
(property) exact: true
exact
: true,
(property) as: "Option"
as
: "Option" })
55
},
56
{
57
(property) decode: (input: { readonly id: number; readonly name: string; }, options: ParseOptions, ast: Transformation) => Effect.Effect<{ readonly id: number; readonly name: string; readonly age?: number; }, ParseResult.ParseIssue, never>
decode
: (
(parameter) input: { readonly id: number; readonly name: string; }
input
) =>
58
import Effect
Effect
.
const mapBoth: <number, Error, never, ParseResult.Type, { age: number; id: number; name: string; } | { id: number; name: string; }>(self: Effect.Effect<number, Error, never>, options: { ...; }) => Effect.Effect<...> (+1 overload)

Returns an effect whose failure and success channels have been mapped by the specified `onFailure` and `onSuccess` functions.

mapBoth
(
function getAge(id: number): Effect.Effect<number, Error>
getAge
(
(parameter) input: { readonly id: number; readonly name: string; }
input
.
(property) id: number
id
), {
59
(property) onFailure: (e: Error) => ParseResult.Type
onFailure
: (
(parameter) e: Error
e
) =>
60
new
import ParseResult
ParseResult
.
constructor Type(ast: AST, actual: unknown, message?: string | undefined): ParseResult.Type

The `Type` variant of the `ParseIssue` type represents an error that occurs when the `actual` value is not of the expected type. The `ast` field specifies the expected type, and the `actual` field contains the value that caused the error.

Type
(
import Schema
Schema
.
(alias) class String export String
String
.
(property) Schema<in out A, in out I = A, out R = never>.ast: AST
ast
,
(parameter) input: { readonly id: number; readonly name: string; }
input
,
(parameter) e: Error
e
.
(property) Error.message: string
message
),
61
// must return { age?: number }
62
(property) onSuccess: (a: number) => { age: number; id: number; name: string; } | { id: number; name: string; }
onSuccess
: (
(parameter) age: number
age
) => (
(parameter) age: number
age
> 18 ? { ...
(parameter) input: { readonly id: number; readonly name: string; }
input
,
(property) age: number
age
} : { ...
(parameter) input: { readonly id: number; readonly name: string; }
input
})
63
}),
64
(property) encode: (input: { readonly id: number; readonly name: string; readonly age?: number; }, options: ParseOptions, ast: Transformation) => Effect.Effect<...>
encode
:
import ParseResult
ParseResult
.
const succeed: <A>(a: A) => Either<A, ParseResult.ParseIssue>
succeed
65
}
66
) {}
67
68
import Schema
Schema
.
const decodeUnknownPromise: <PersonWithTransformFrom, { readonly id: number; readonly name: string; }>(schema: Schema.Schema<PersonWithTransformFrom, { readonly id: number; readonly name: string; }, never>, options?: ParseOptions) => (u: unknown, overrideOptions?: ParseOptions) => Promise<...>
decodeUnknownPromise
(
class PersonWithTransformFrom
PersonWithTransformFrom
)({
69
(property) id: number
id
: 1,
70
(property) name: string
name
: "name"
71
}).
(method) Promise<PersonWithTransformFrom>.then<void, never>(onfulfilled?: ((value: PersonWithTransformFrom) => void | PromiseLike<void>) | null | undefined, onrejected?: ((reason: any) => PromiseLike<never>) | null | undefined): Promise<...>

Attaches callbacks for the resolution and/or rejection of the Promise.

then
(
namespace console var console: Console

The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v22.x/api/process.html#processstderr). The global `console` can be used without importing the `node:console` module. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v22.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```

console
.
(method) Console.log(message?: any, ...optionalParams: any[]): void

Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v22.x/api/util.html#utilformatformat-args) for more information.

log
)
72
/*
73
Output:
74
PersonWithTransformFrom {
75
id: 1,
76
name: 'name',
77
age: { _id: 'Option', _tag: 'None' }
78
}
79
*/

The decision of which API to use, either transformOrFail or transformOrFailFrom, depends on when you wish to execute the transformation:

  1. Using transformOrFail:

    • The transformation occurs at the end of the process.
    • It expects you to provide a value of type { age: Option<number> }.
    • After processing the initial input, the new transformation comes into play, and you need to ensure the final output adheres to the specified structure.
  2. Using transformOrFailFrom:

    • The new transformation starts as soon as the initial input is handled.
    • You should provide a value { age?: number }.
    • Based on this fresh input, the subsequent transformation { age: Schema.optionalToOption(S.Number, { exact: true }) } is executed.
    • This approach allows for immediate handling of the input, potentially influencing the subsequent transformations.