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 using Schema.Class, you need to specify:

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

Example (Defining a Schema Class)

import {
import Schema
Schema
} from "effect"
class
class Person
Person
extends
import Schema
Schema
.
const Class: <Person>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: ClassAnnotations<Person, Schema.Struct<Fields extends Schema.Struct.Fields>.Type<Fields>> | undefined) => Schema.Class<...>

@example

import { Schema } from "effect"
class MyClass extends Schema.Class<MyClass>("MyClass")({
someField: Schema.String
}) {
someMethod() {
return this.someField + "bar"
}
}

@since3.10.0

Class
<
class Person
Person
>("Person")({
id: typeof Schema.Number
id
:
import Schema
Schema
.
class Number
export Number

@since3.10.0

Number
,
name: typeof Schema.NonEmptyString
name
:
import Schema
Schema
.
class NonEmptyString

@since3.10.0

NonEmptyString
}) {}

In this example, Person is both a schema and a TypeScript class. Instances of Person are created using the defined schema, ensuring compliance with the specified fields.

Example (Creating Instances)

import {
import Schema
Schema
} from "effect"
class
class Person
Person
extends
import Schema
Schema
.
const Class: <Person>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: ClassAnnotations<Person, Schema.Struct<Fields extends Schema.Struct.Fields>.Type<Fields>> | undefined) => Schema.Class<...>

@example

import { Schema } from "effect"
class MyClass extends Schema.Class<MyClass>("MyClass")({
someField: Schema.String
}) {
someMethod() {
return this.someField + "bar"
}
}

@since3.10.0

Class
<
class Person
Person
>("Person")({
id: typeof Schema.Number
id
:
import Schema
Schema
.
class Number
export Number

@since3.10.0

Number
,
name: typeof Schema.NonEmptyString
name
:
import Schema
Schema
.
class NonEmptyString

@since3.10.0

NonEmptyString
}) {}
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 and process.stderr. 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 for more information.

Example using the global console:

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:

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

@seesource

console
.
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) (the arguments are all passed to util.format()).

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() for more information.

@sincev0.1.100

log
(new
constructor Person(props: {
readonly id: number;
readonly name: string;
}, options?: MakeOptions): Person
Person
({
id: number
id
: 1,
name: string
name
: "John" }))
/*
Output:
Person { id: 1, name: 'John' }
*/
// Using the factory function
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 and process.stderr. 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 for more information.

Example using the global console:

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:

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

@seesource

console
.
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) (the arguments are all passed to util.format()).

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() for more information.

@sincev0.1.100

log
(
class Person
Person
.
Class<Person, { id: typeof Number$; name: typeof NonEmptyString; }, Struct<Fields extends Struct.Fields>.Encoded<{ id: typeof Number$; name: typeof NonEmptyString; }>, never, { ...; } & { ...; }, {}, {}>.make<[{
id: number;
name: string;
}], Person>(this: new (args_0: {
id: number;
name: string;
}) => Person, args_0: {
id: number;
name: string;
}): Person
make
({
id: number
id
: 1,
name: string
name
: "John" }))
/*
Output:
Person { id: 1, name: 'John' }
*/

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

Example (Defining and Using a Class Without Arguments)

import {
import Schema
Schema
} from "effect"
// Define a class with no fields
class
class NoArgs
NoArgs
extends
import Schema
Schema
.
const Class: <NoArgs>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: ClassAnnotations<NoArgs, Schema.Struct<Fields extends Schema.Struct.Fields>.Type<Fields>> | undefined) => Schema.Class<...>

@example

import { Schema } from "effect"
class MyClass extends Schema.Class<MyClass>("MyClass")({
someField: Schema.String
}) {
someMethod() {
return this.someField + "bar"
}
}

@since3.10.0

Class
<
class NoArgs
NoArgs
>("NoArgs")({}) {}
// Create an instance using the default constructor
const
const noargs1: NoArgs
noargs1
= new
constructor NoArgs(props: void | {}, options?: MakeOptions): NoArgs
NoArgs
()
// Alternatively, create an instance by explicitly passing an empty object
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.

The constructor ensures that each property, like id and name, adheres to the schema. For instance, id must be a number, and name must be a non-empty string.

Example (Creating a Valid Instance)

import {
import Schema
Schema
} from "effect"
class
class Person
Person
extends
import Schema
Schema
.
const Class: <Person>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: ClassAnnotations<Person, Schema.Struct<Fields extends Schema.Struct.Fields>.Type<Fields>> | undefined) => Schema.Class<...>

@example

import { Schema } from "effect"
class MyClass extends Schema.Class<MyClass>("MyClass")({
someField: Schema.String
}) {
someMethod() {
return this.someField + "bar"
}
}

@since3.10.0

Class
<
class Person
Person
>("Person")({
id: typeof Schema.Number
id
:
import Schema
Schema
.
class Number
export Number

@since3.10.0

Number
,
name: typeof Schema.NonEmptyString
name
:
import Schema
Schema
.
class NonEmptyString

@since3.10.0

NonEmptyString
}) {}
// Create an instance with valid properties
const
const john: Person
john
= new
constructor Person(props: {
readonly id: number;
readonly name: string;
}, options?: MakeOptions): Person
Person
({
id: number
id
: 1,
name: string
name
: "John" })

If invalid properties are provided during instantiation, the constructor throws an error, explaining why the validation failed.

Example (Creating an Instance with Invalid Properties)

import {
import Schema
Schema
} from "effect"
class
class Person
Person
extends
import Schema
Schema
.
const Class: <Person>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: ClassAnnotations<Person, Schema.Struct<Fields extends Schema.Struct.Fields>.Type<Fields>> | undefined) => Schema.Class<...>

@example

import { Schema } from "effect"
class MyClass extends Schema.Class<MyClass>("MyClass")({
someField: Schema.String
}) {
someMethod() {
return this.someField + "bar"
}
}

@since3.10.0

Class
<
class Person
Person
>("Person")({
id: typeof Schema.Number
id
:
import Schema
Schema
.
class Number
export Number

@since3.10.0

Number
,
name: typeof Schema.NonEmptyString
name
:
import Schema
Schema
.
class NonEmptyString

@since3.10.0

NonEmptyString
}) {}
// Attempt to create an instance with an invalid `name`
new
constructor Person(props: {
readonly id: number;
readonly name: string;
}, options?: MakeOptions): Person
Person
({
id: number
id
: 1,
name: string
name
: "" })
/*
throws:
ParseError: Person (Constructor)
└─ ["name"]
└─ NonEmptyString
└─ Predicate refinement failure
└─ Expected NonEmptyString, actual ""
*/

The error clearly specifies that the name field failed to meet the NonEmptyString requirement.

In some scenarios, you might want to bypass the validation logic. While not generally recommended, the library provides an option to do so.

Example (Bypassing Validation)

import {
import Schema
Schema
} from "effect"
class
class Person
Person
extends
import Schema
Schema
.
const Class: <Person>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: ClassAnnotations<Person, Schema.Struct<Fields extends Schema.Struct.Fields>.Type<Fields>> | undefined) => Schema.Class<...>

@example

import { Schema } from "effect"
class MyClass extends Schema.Class<MyClass>("MyClass")({
someField: Schema.String
}) {
someMethod() {
return this.someField + "bar"
}
}

@since3.10.0

Class
<
class Person
Person
>("Person")({
id: typeof Schema.Number
id
:
import Schema
Schema
.
class Number
export Number

@since3.10.0

Number
,
name: typeof Schema.NonEmptyString
name
:
import Schema
Schema
.
class NonEmptyString

@since3.10.0

NonEmptyString
}) {}
// Bypass validation during instantiation
const
const john: Person
john
= new
constructor Person(props: {
readonly id: number;
readonly name: string;
}, options?: MakeOptions): Person
Person
({
id: number
id
: 1,
name: string
name
: "" }, true)
// Or use the `disableValidation` option explicitly
new
constructor Person(props: {
readonly id: number;
readonly name: string;
}, options?: MakeOptions): Person
Person
({
id: number
id
: 1,
name: string
name
: "" }, {
disableValidation?: boolean
disableValidation
: true })

Instances of classes created with Schema.Class support the Equal trait through their integration with Data.Class. This enables straightforward value comparisons, even across different instances.

Two class instances are considered equal if their properties have identical values.

Example (Comparing Instances with Equal Properties)

import {
import Schema
Schema
} from "effect"
import {
import Equal
Equal
} from "effect"
class
class Person
Person
extends
import Schema
Schema
.
const Class: <Person>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: ClassAnnotations<Person, Schema.Struct<Fields extends Schema.Struct.Fields>.Type<Fields>> | undefined) => Schema.Class<...>

@example

import { Schema } from "effect"
class MyClass extends Schema.Class<MyClass>("MyClass")({
someField: Schema.String
}) {
someMethod() {
return this.someField + "bar"
}
}

@since3.10.0

Class
<
class Person
Person
>("Person")({
id: typeof Schema.Number
id
:
import Schema
Schema
.
class Number
export Number

@since3.10.0

Number
,
name: typeof Schema.NonEmptyString
name
:
import Schema
Schema
.
class NonEmptyString

@since3.10.0

NonEmptyString
}) {}
const
const john1: Person
john1
= new
constructor Person(props: {
readonly id: number;
readonly name: string;
}, options?: MakeOptions): Person
Person
({
id: number
id
: 1,
name: string
name
: "John" })
const
const john2: Person
john2
= new
constructor Person(props: {
readonly id: number;
readonly name: string;
}, options?: MakeOptions): Person
Person
({
id: number
id
: 1,
name: string
name
: "John" })
// Compare instances
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 and process.stderr. 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 for more information.

Example using the global console:

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:

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

@seesource

console
.
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) (the arguments are all passed to util.format()).

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() for more information.

@sincev0.1.100

log
(
import Equal
Equal
.
function equals<Person, Person>(self: Person, that: Person): boolean (+1 overload)

@since2.0.0

equals
(
const john1: Person
john1
,
const john2: Person
john2
))
// Output: true

The Equal trait performs comparisons at the first level. If a property is a more complex structure, such as an array, instances may not be considered equal, even if the arrays themselves have identical values.

Example (Shallow Equality for Arrays)

import {
import Schema
Schema
} from "effect"
import {
import Equal
Equal
} from "effect"
class
class Person
Person
extends
import Schema
Schema
.
const Class: <Person>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: ClassAnnotations<Person, Schema.Struct<Fields extends Schema.Struct.Fields>.Type<Fields>> | undefined) => Schema.Class<...>

@example

import { Schema } from "effect"
class MyClass extends Schema.Class<MyClass>("MyClass")({
someField: Schema.String
}) {
someMethod() {
return this.someField + "bar"
}
}

@since3.10.0

Class
<
class Person
Person
>("Person")({
id: typeof Schema.Number
id
:
import Schema
Schema
.
class Number
export Number

@since3.10.0

Number
,
name: typeof Schema.NonEmptyString
name
:
import Schema
Schema
.
class NonEmptyString

@since3.10.0

NonEmptyString
,
hobbies: Schema.Array$<typeof Schema.String>
hobbies
:
import Schema
Schema
.
Array<typeof Schema.String>(value: typeof Schema.String): Schema.Array$<typeof Schema.String>
export Array

@since3.10.0

Array
(
import Schema
Schema
.
class String
export String

@since3.10.0

String
) // Standard array schema
}) {}
const
const john1: Person
john1
= new
constructor Person(props: {
readonly id: number;
readonly name: string;
readonly hobbies: readonly string[];
}, options?: MakeOptions): Person
Person
({
id: number
id
: 1,
name: string
name
: "John",
hobbies: readonly string[]
hobbies
: ["reading", "coding"]
})
const
const john2: Person
john2
= new
constructor Person(props: {
readonly id: number;
readonly name: string;
readonly hobbies: readonly string[];
}, options?: MakeOptions): Person
Person
({
id: number
id
: 1,
name: string
name
: "John",
hobbies: readonly string[]
hobbies
: ["reading", "coding"]
})
// Equality fails because `hobbies` are not deeply compared
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 and process.stderr. 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 for more information.

Example using the global console:

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:

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

@seesource

console
.
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) (the arguments are all passed to util.format()).

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() for more information.

@sincev0.1.100

log
(
import Equal
Equal
.
function equals<Person, Person>(self: Person, that: Person): boolean (+1 overload)

@since2.0.0

equals
(
const john1: Person
john1
,
const john2: Person
john2
))
// Output: false

To achieve deep equality for nested structures like arrays, use Schema.Data in combination with Data.array. This enables the library to compare each element of the array rather than treating it as a single entity.

Example (Using Schema.Data for Deep Equality)

import {
import Schema
Schema
} from "effect"
import {
import Data
Data
,
import Equal
Equal
} from "effect"
class
class Person
Person
extends
import Schema
Schema
.
const Class: <Person>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: ClassAnnotations<Person, Schema.Struct<Fields extends Schema.Struct.Fields>.Type<Fields>> | undefined) => Schema.Class<...>

@example

import { Schema } from "effect"
class MyClass extends Schema.Class<MyClass>("MyClass")({
someField: Schema.String
}) {
someMethod() {
return this.someField + "bar"
}
}

@since3.10.0

Class
<
class Person
Person
>("Person")({
id: typeof Schema.Number
id
:
import Schema
Schema
.
class Number
export Number

@since3.10.0

Number
,
name: typeof Schema.NonEmptyString
name
:
import Schema
Schema
.
class NonEmptyString

@since3.10.0

NonEmptyString
,
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>

@since3.10.0

Data
(
import Schema
Schema
.
Array<typeof Schema.String>(value: typeof Schema.String): Schema.Array$<typeof Schema.String>
export Array

@since3.10.0

Array
(
import Schema
Schema
.
class String
export String

@since3.10.0

String
)) // Enable deep equality
}) {}
const
const john1: Person
john1
= new
constructor Person(props: {
readonly id: number;
readonly name: string;
readonly hobbies: readonly string[];
}, options?: MakeOptions): Person
Person
({
id: number
id
: 1,
name: string
name
: "John",
hobbies: readonly string[]
hobbies
:
import Data
Data
.
const array: <string[]>(as: string[]) => readonly string[]

@example

import { Data, Equal } from "effect"
const alice = Data.struct({ name: "Alice", age: 30 })
const bob = Data.struct({ name: "Bob", age: 40 })
const persons = Data.array([alice, bob])
assert.deepStrictEqual(
Equal.equals(
persons,
Data.array([
Data.struct({ name: "Alice", age: 30 }),
Data.struct({ name: "Bob", age: 40 })
])
),
true
)

@since2.0.0

array
(["reading", "coding"])
})
const
const john2: Person
john2
= new
constructor Person(props: {
readonly id: number;
readonly name: string;
readonly hobbies: readonly string[];
}, options?: MakeOptions): Person
Person
({
id: number
id
: 1,
name: string
name
: "John",
hobbies: readonly string[]
hobbies
:
import Data
Data
.
const array: <string[]>(as: string[]) => readonly string[]

@example

import { Data, Equal } from "effect"
const alice = Data.struct({ name: "Alice", age: 30 })
const bob = Data.struct({ name: "Bob", age: 40 })
const persons = Data.array([alice, bob])
assert.deepStrictEqual(
Equal.equals(
persons,
Data.array([
Data.struct({ name: "Alice", age: 30 }),
Data.struct({ name: "Bob", age: 40 })
])
),
true
)

@since2.0.0

array
(["reading", "coding"])
})
// Equality succeeds because `hobbies` are deeply compared
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 and process.stderr. 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 for more information.

Example using the global console:

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:

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

@seesource

console
.
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) (the arguments are all passed to util.format()).

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() for more information.

@sincev0.1.100

log
(
import Equal
Equal
.
function equals<Person, Person>(self: Person, that: Person): boolean (+1 overload)

@since2.0.0

equals
(
const john1: Person
john1
,
const john2: Person
john2
))
// Output: true

Schema classes provide the flexibility to include custom getters and methods, allowing you to extend their functionality beyond the defined fields.

A getter can be used to derive computed values from the fields of the class. For example, a Person class can include a getter to return the name property in uppercase.

Example (Adding a Getter for Uppercase Name)

import {
import Schema
Schema
} from "effect"
class
class Person
Person
extends
import Schema
Schema
.
const Class: <Person>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: ClassAnnotations<Person, Schema.Struct<Fields extends Schema.Struct.Fields>.Type<Fields>> | undefined) => Schema.Class<...>

@example

import { Schema } from "effect"
class MyClass extends Schema.Class<MyClass>("MyClass")({
someField: Schema.String
}) {
someMethod() {
return this.someField + "bar"
}
}

@since3.10.0

Class
<
class Person
Person
>("Person")({
id: typeof Schema.Number
id
:
import Schema
Schema
.
class Number
export Number

@since3.10.0

Number
,
name: typeof Schema.NonEmptyString
name
:
import Schema
Schema
.
class NonEmptyString

@since3.10.0

NonEmptyString
}) {
// Custom getter to return the name in uppercase
get
Person.upperName: string
upperName
() {
return this.
name: string
name
.
String.toUpperCase(): string

Converts all the alphabetic characters in a string to uppercase.

toUpperCase
()
}
}
const
const john: Person
john
= new
constructor Person(props: {
readonly id: number;
readonly name: string;
}, options?: MakeOptions): Person
Person
({
id: number
id
: 1,
name: string
name
: "John" })
// Use the custom getter
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 and process.stderr. 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 for more information.

Example using the global console:

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:

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

@seesource

console
.
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) (the arguments are all passed to util.format()).

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() for more information.

@sincev0.1.100

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

In addition to getters, you can define methods to encapsulate more complex logic or operations involving the class’s fields.

Example (Adding a Method)

import {
import Schema
Schema
} from "effect"
class
class Person
Person
extends
import Schema
Schema
.
const Class: <Person>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: ClassAnnotations<Person, Schema.Struct<Fields extends Schema.Struct.Fields>.Type<Fields>> | undefined) => Schema.Class<...>

@example

import { Schema } from "effect"
class MyClass extends Schema.Class<MyClass>("MyClass")({
someField: Schema.String
}) {
someMethod() {
return this.someField + "bar"
}
}

@since3.10.0

Class
<
class Person
Person
>("Person")({
id: typeof Schema.Number
id
:
import Schema
Schema
.
class Number
export Number

@since3.10.0

Number
,
name: typeof Schema.NonEmptyString
name
:
import Schema
Schema
.
class NonEmptyString

@since3.10.0

NonEmptyString
}) {
// Custom method to return a greeting
Person.greet(): string
greet
() {
return `Hello, my name is ${this.
name: string
name
}.`
}
}
const
const john: Person
john
= new
constructor Person(props: {
readonly id: number;
readonly name: string;
}, options?: MakeOptions): Person
Person
({
id: number
id
: 1,
name: string
name
: "John" })
// Use the custom method
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 and process.stderr. 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 for more information.

Example using the global console:

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:

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

@seesource

console
.
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) (the arguments are all passed to util.format()).

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() for more information.

@sincev0.1.100

log
(
const john: Person
john
.
Person.greet(): string
greet
())
// Output: "Hello, my name is John."

When you define a class with Schema.Class, it serves both as a schema and as a class. This dual functionality allows the class to be used wherever a schema is required.

Example (Using a Class in an Array Schema)

import {
import Schema
Schema
} from "effect"
class
class Person
Person
extends
import Schema
Schema
.
const Class: <Person>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: ClassAnnotations<Person, Schema.Struct<Fields extends Schema.Struct.Fields>.Type<Fields>> | undefined) => Schema.Class<...>

@example

import { Schema } from "effect"
class MyClass extends Schema.Class<MyClass>("MyClass")({
someField: Schema.String
}) {
someMethod() {
return this.someField + "bar"
}
}

@since3.10.0

Class
<
class Person
Person
>("Person")({
id: typeof Schema.Number
id
:
import Schema
Schema
.
class Number
export Number

@since3.10.0

Number
,
name: typeof Schema.NonEmptyString
name
:
import Schema
Schema
.
class NonEmptyString

@since3.10.0

NonEmptyString
}) {}
// Use the Person class in an array schema
const
const Persons: Schema.Array$<typeof Person>
Persons
=
import Schema
Schema
.
Array<typeof Person>(value: typeof Person): Schema.Array$<typeof Person>
export Array

@since3.10.0

Array
(
class Person
Person
)
// ┌─── readonly Person[]
// ▼
type
type Type = readonly Person[]
Type
= typeof
const Persons: Schema.Array$<typeof Person>
Persons
.
Schema<readonly Person[], readonly { readonly id: number; readonly name: string; }[], never>.Type: readonly Person[]
Type

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

Example (Accessing the fields Property)

import {
import Schema
Schema
} from "effect"
class
class Person
Person
extends
import Schema
Schema
.
const Class: <Person>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: ClassAnnotations<Person, Schema.Struct<Fields extends Schema.Struct.Fields>.Type<Fields>> | undefined) => Schema.Class<...>

@example

import { Schema } from "effect"
class MyClass extends Schema.Class<MyClass>("MyClass")({
someField: Schema.String
}) {
someMethod() {
return this.someField + "bar"
}
}

@since3.10.0

Class
<
class Person
Person
>("Person")({
id: typeof Schema.Number
id
:
import Schema
Schema
.
class Number
export Number

@since3.10.0

Number
,
name: typeof Schema.NonEmptyString
name
:
import Schema
Schema
.
class NonEmptyString

@since3.10.0

NonEmptyString
}) {}
// ┌─── {
// | readonly id: typeof Schema.Number;
// | readonly name: typeof Schema.NonEmptyString;
// | }
// ▼
class Person
Person
.
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

Defining a class with Schema.Class is similar to creating a transformation schema that converts a struct schema into a declaration schema representing the class type.

For example, consider the following class definition:

import {
import Schema
Schema
} from "effect"
class
class Person
Person
extends
import Schema
Schema
.
const Class: <Person>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: ClassAnnotations<Person, Schema.Struct<Fields extends Schema.Struct.Fields>.Type<Fields>> | undefined) => Schema.Class<...>

@example

import { Schema } from "effect"
class MyClass extends Schema.Class<MyClass>("MyClass")({
someField: Schema.String
}) {
someMethod() {
return this.someField + "bar"
}
}

@since3.10.0

Class
<
class Person
Person
>("Person")({
id: typeof Schema.Number
id
:
import Schema
Schema
.
class Number
export Number

@since3.10.0

Number
,
name: typeof Schema.NonEmptyString
name
:
import Schema
Schema
.
class NonEmptyString

@since3.10.0

NonEmptyString
}) {}

Under the hood, this definition creates a transformation schema that maps:

Schema.Struct({
id: Schema.Number,
name: Schema.NonEmptyString
})

to a schema representing the Person class:

Schema.declare((input) => input instanceof Person)

So, defining a schema with Schema.Class involves three schemas:

  • The “from” schema (the struct)
  • The “to” schema (the class)
  • The “transformation” schema (struct -> class)

You can annotate each of these schemas by passing a tuple as the second argument to the Schema.Class API.

Example (Annotating Different Parts of the Class Schema)

import {
import Schema
Schema
,
import SchemaAST
SchemaAST
} from "effect"
class
class Person
Person
extends
import Schema
Schema
.
const Class: <Person>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: ClassAnnotations<Person, Schema.Struct<Fields extends Schema.Struct.Fields>.Type<Fields>> | undefined) => Schema.Class<...>

@example

import { Schema } from "effect"
class MyClass extends Schema.Class<MyClass>("MyClass")({
someField: Schema.String
}) {
someMethod() {
return this.someField + "bar"
}
}

@since3.10.0

Class
<
class Person
Person
>("Person")(
{
id: typeof Schema.Number
id
:
import Schema
Schema
.
class Number
export Number

@since3.10.0

Number
,
name: typeof Schema.NonEmptyString
name
:
import Schema
Schema
.
class NonEmptyString

@since3.10.0

NonEmptyString
},
[
// Annotations for the "to" schema
{
Annotations.Doc<Person>.description?: string
description
: `"to" description` },
// Annotations for the "transformation schema
{
Annotations.Doc<Person>.description?: string
description
: `"transformation" description` },
// Annotations for the "from" schema
{
Annotations.Doc<A>.description?: string
description
: `"from" description` }
]
) {}
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 and process.stderr. 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 for more information.

Example using the global console:

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:

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

@seesource

console
.
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) (the arguments are all passed to util.format()).

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() for more information.

@sincev0.1.100

log
(
import SchemaAST
SchemaAST
.
const getDescriptionAnnotation: (annotated: SchemaAST.Annotated) => Option<string>

@since3.10.0

getDescriptionAnnotation
(
class Person
Person
.
Class<Person, { id: typeof Number$; name: typeof NonEmptyString; }, Struct<Fields extends Struct.Fields>.Encoded<{ id: typeof Number$; name: typeof NonEmptyString; }>, never, { ...; } & { ...; }, {}, {}>.ast: SchemaAST.Transformation

@since3.10.0

ast
.
Transformation.to: SchemaAST.AST
to
))
// Output: { _id: 'Option', _tag: 'Some', value: '"to" description' }
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 and process.stderr. 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 for more information.

Example using the global console:

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:

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

@seesource

console
.
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) (the arguments are all passed to util.format()).

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() for more information.

@sincev0.1.100

log
(
import SchemaAST
SchemaAST
.
const getDescriptionAnnotation: (annotated: SchemaAST.Annotated) => Option<string>

@since3.10.0

getDescriptionAnnotation
(
class Person
Person
.
Class<Person, { id: typeof Number$; name: typeof NonEmptyString; }, Struct<Fields extends Struct.Fields>.Encoded<{ id: typeof Number$; name: typeof NonEmptyString; }>, never, { ...; } & { ...; }, {}, {}>.ast: SchemaAST.Transformation

@since3.10.0

ast
))
// Output: { _id: 'Option', _tag: 'Some', value: '"transformation" description' }
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 and process.stderr. 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 for more information.

Example using the global console:

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:

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

@seesource

console
.
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) (the arguments are all passed to util.format()).

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() for more information.

@sincev0.1.100

log
(
import SchemaAST
SchemaAST
.
const getDescriptionAnnotation: (annotated: SchemaAST.Annotated) => Option<string>

@since3.10.0

getDescriptionAnnotation
(
class Person
Person
.
Class<Person, { id: typeof Number$; name: typeof NonEmptyString; }, Struct<Fields extends Struct.Fields>.Encoded<{ id: typeof Number$; name: typeof NonEmptyString; }>, never, { ...; } & { ...; }, {}, {}>.ast: SchemaAST.Transformation

@since3.10.0

ast
.
Transformation.from: SchemaAST.AST
from
))
// Output: { _id: 'Option', _tag: 'Some', value: '"from" description' }

If you do not want to annotate all three schemas, you can pass undefined for the ones you wish to skip.

Example (Skipping Annotations)

import {
import Schema
Schema
,
import SchemaAST
SchemaAST
} from "effect"
class
class Person
Person
extends
import Schema
Schema
.
const Class: <Person>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: ClassAnnotations<Person, Schema.Struct<Fields extends Schema.Struct.Fields>.Type<Fields>> | undefined) => Schema.Class<...>

@example

import { Schema } from "effect"
class MyClass extends Schema.Class<MyClass>("MyClass")({
someField: Schema.String
}) {
someMethod() {
return this.someField + "bar"
}
}

@since3.10.0

Class
<
class Person
Person
>("Person")(
{
id: typeof Schema.Number
id
:
import Schema
Schema
.
class Number
export Number

@since3.10.0

Number
,
name: typeof Schema.NonEmptyString
name
:
import Schema
Schema
.
class NonEmptyString

@since3.10.0

NonEmptyString
},
[
// No annotations for the "to" schema
var undefined
undefined
,
// Annotations for the "transformation schema
{
Annotations.Doc<Person>.description?: string
description
: `"transformation" description` }
]
) {}
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 and process.stderr. 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 for more information.

Example using the global console:

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:

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

@seesource

console
.
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) (the arguments are all passed to util.format()).

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() for more information.

@sincev0.1.100

log
(
import SchemaAST
SchemaAST
.
const getDescriptionAnnotation: (annotated: SchemaAST.Annotated) => Option<string>

@since3.10.0

getDescriptionAnnotation
(
class Person
Person
.
Class<Person, { id: typeof Number$; name: typeof NonEmptyString; }, Struct<Fields extends Struct.Fields>.Encoded<{ id: typeof Number$; name: typeof NonEmptyString; }>, never, { ...; } & { ...; }, {}, {}>.ast: SchemaAST.Transformation

@since3.10.0

ast
.
Transformation.to: SchemaAST.AST
to
))
// Output: { _id: 'Option', _tag: 'None' }
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 and process.stderr. 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 for more information.

Example using the global console:

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:

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

@seesource

console
.
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) (the arguments are all passed to util.format()).

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() for more information.

@sincev0.1.100

log
(
import SchemaAST
SchemaAST
.
const getDescriptionAnnotation: (annotated: SchemaAST.Annotated) => Option<string>

@since3.10.0

getDescriptionAnnotation
(
class Person
Person
.
Class<Person, { id: typeof Number$; name: typeof NonEmptyString; }, Struct<Fields extends Struct.Fields>.Encoded<{ id: typeof Number$; name: typeof NonEmptyString; }>, never, { ...; } & { ...; }, {}, {}>.ast: SchemaAST.Transformation

@since3.10.0

ast
))
// Output: { _id: 'Option', _tag: 'Some', value: '"transformation" description' }
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 and process.stderr. 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 for more information.

Example using the global console:

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:

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

@seesource

console
.
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) (the arguments are all passed to util.format()).

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() for more information.

@sincev0.1.100

log
(
import SchemaAST
SchemaAST
.
const getDescriptionAnnotation: (annotated: SchemaAST.Annotated) => Option<string>

@since3.10.0

getDescriptionAnnotation
(
class Person
Person
.
Class<Person, { id: typeof Number$; name: typeof NonEmptyString; }, Struct<Fields extends Struct.Fields>.Encoded<{ id: typeof Number$; name: typeof NonEmptyString; }>, never, { ...; } & { ...; }, {}, {}>.ast: SchemaAST.Transformation

@since3.10.0

ast
.
Transformation.from: SchemaAST.AST
from
))
// Output: { _id: 'Option', _tag: 'None' }

By default, the unique identifier used to define the class is also applied as the default identifier annotation for the Class Schema.

Example (Default Identifier Annotation)

import {
import Schema
Schema
,
import SchemaAST
SchemaAST
} from "effect"
// Used as default identifier annotation ────┐
// |
// ▼
class
class Person
Person
extends
import Schema
Schema
.
const Class: <Person>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: ClassAnnotations<Person, Schema.Struct<Fields extends Schema.Struct.Fields>.Type<Fields>> | undefined) => Schema.Class<...>

@example

import { Schema } from "effect"
class MyClass extends Schema.Class<MyClass>("MyClass")({
someField: Schema.String
}) {
someMethod() {
return this.someField + "bar"
}
}

@since3.10.0

Class
<
class Person
Person
>("Person")({
id: typeof Schema.Number
id
:
import Schema
Schema
.
class Number
export Number

@since3.10.0

Number
,
name: typeof Schema.NonEmptyString
name
:
import Schema
Schema
.
class NonEmptyString

@since3.10.0

NonEmptyString
}) {}
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 and process.stderr. 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 for more information.

Example using the global console:

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:

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

@seesource

console
.
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) (the arguments are all passed to util.format()).

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() for more information.

@sincev0.1.100

log
(
import SchemaAST
SchemaAST
.
const getIdentifierAnnotation: (annotated: SchemaAST.Annotated) => Option<string>

@since3.10.0

getIdentifierAnnotation
(
class Person
Person
.
Class<Person, { id: typeof Number$; name: typeof NonEmptyString; }, Struct<Fields extends Struct.Fields>.Encoded<{ id: typeof Number$; name: typeof NonEmptyString; }>, never, { ...; } & { ...; }, {}, {}>.ast: SchemaAST.Transformation

@since3.10.0

ast
.
Transformation.to: SchemaAST.AST
to
))
// Output: { _id: 'Option', _tag: 'Some', value: 'Person' }

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.

Example (Self-Referencing Schema)

import {
import Schema
Schema
} from "effect"
// Define a Category schema with a recursive subcategories field
class
class Category
Category
extends
import Schema
Schema
.
const Class: <Category>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: ClassAnnotations<Category, Schema.Struct<Fields extends Schema.Struct.Fields>.Type<Fields>> | undefined) => Schema.Class<...>

@example

import { Schema } from "effect"
class MyClass extends Schema.Class<MyClass>("MyClass")({
someField: Schema.String
}) {
someMethod() {
return this.someField + "bar"
}
}

@since3.10.0

Class
<
class Category
Category
>("Category")({
name: typeof Schema.String
name
:
import Schema
Schema
.
class String
export String

@since3.10.0

String
,
subcategories: Schema.Array$<Schema.suspend<Category, Category, never>>
subcategories
:
import Schema
Schema
.
Array<Schema.suspend<Category, Category, never>>(value: Schema.suspend<Category, Category, never>): Schema.Array$<Schema.suspend<Category, Category, never>>
export Array

@since3.10.0

Array
(
import Schema
Schema
.
const suspend: <Category, Category, never>(f: () => Schema.Schema<Category, Category, never>) => Schema.suspend<Category, Category, never>

@since3.10.0

suspend
(():
import Schema
Schema
.
interface Schema<in out A, in out I = A, out R = never>

@since3.10.0

@since3.10.0

Schema
<
class Category
Category
> =>
class Category
Category
)
)
}) {}

Example (Missing Type Annotation Error)

import {
import Schema
Schema
} from "effect"
// @ts-expect-error
class
class Category
Category
extends
import Schema
Schema
.
const Class: <Category>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: ClassAnnotations<Category, Schema.Struct<Fields extends Schema.Struct.Fields>.Type<Fields>> | undefined) => Schema.Class<...>

@example

import { Schema } from "effect"
class MyClass extends Schema.Class<MyClass>("MyClass")({
someField: Schema.String
}) {
someMethod() {
return this.someField + "bar"
}
}

@since3.10.0

Class
<
class Category
Category
>("Category")({
name: typeof Schema.String
name
:
import Schema
Schema
.
class String
export String

@since3.10.0

String
,
// @ts-expect-error: TypeScript cannot infer the recursive type
subcategories: Schema.Array$<Schema.suspend<unknown, unknown, unknown>>
subcategories
:
import Schema
Schema
.
Array<Schema.suspend<unknown, unknown, unknown>>(value: Schema.suspend<unknown, unknown, unknown>): Schema.Array$<Schema.suspend<unknown, unknown, unknown>>
export Array

@since3.10.0

Array
(
import Schema
Schema
.
const suspend: <unknown, unknown, unknown>(f: () => Schema.Schema<unknown, unknown, unknown>) => Schema.suspend<unknown, unknown, unknown>

@since3.10.0

suspend
(() =>
class Category
Category
))
}) {}
/*
'Category' is referenced directly or indirectly in its own base expression.ts(2506)
*/

Sometimes, schemas depend on each other in a mutually recursive way. For instance, an arithmetic expression tree might include Expression nodes that can either be numbers or Operation nodes, which in turn reference Expression nodes.

Example (Arithmetic Expression Tree)

import {
import Schema
Schema
} from "effect"
class
class Expression
Expression
extends
import Schema
Schema
.
const Class: <Expression>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: ClassAnnotations<Expression, Schema.Struct<Fields extends Schema.Struct.Fields>.Type<Fields>> | undefined) => Schema.Class<...>

@example

import { Schema } from "effect"
class MyClass extends Schema.Class<MyClass>("MyClass")({
someField: Schema.String
}) {
someMethod() {
return this.someField + "bar"
}
}

@since3.10.0

Class
<
class Expression
Expression
>("Expression")({
type: Schema.Literal<["expression"]>
type
:
import Schema
Schema
.
function Literal<["expression"]>(literals_0: "expression"): Schema.Literal<["expression"]> (+2 overloads)

@since3.10.0

Literal
("expression"),
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)

@since3.10.0

Union
(
import Schema
Schema
.
class Number
export Number

@since3.10.0

Number
,
import Schema
Schema
.
const suspend: <Operation, Operation, never>(f: () => Schema.Schema<Operation, Operation, never>) => Schema.suspend<Operation, Operation, never>

@since3.10.0

suspend
(():
import Schema
Schema
.
interface Schema<in out A, in out I = A, out R = never>

@since3.10.0

@since3.10.0

Schema
<
class Operation
Operation
> =>
class Operation
Operation
)
)
}) {}
class
class Operation
Operation
extends
import Schema
Schema
.
const Class: <Operation>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: ClassAnnotations<Operation, Schema.Struct<Fields extends Schema.Struct.Fields>.Type<Fields>> | undefined) => Schema.Class<...>

@example

import { Schema } from "effect"
class MyClass extends Schema.Class<MyClass>("MyClass")({
someField: Schema.String
}) {
someMethod() {
return this.someField + "bar"
}
}

@since3.10.0

Class
<
class Operation
Operation
>("Operation")({
type: Schema.Literal<["operation"]>
type
:
import Schema
Schema
.
function Literal<["operation"]>(literals_0: "operation"): Schema.Literal<["operation"]> (+2 overloads)

@since3.10.0

Literal
("operation"),
operator: Schema.Literal<["+", "-"]>
operator
:
import Schema
Schema
.
function Literal<["+", "-"]>(literals_0: "+", literals_1: "-"): Schema.Literal<["+", "-"]> (+2 overloads)

@since3.10.0

Literal
("+", "-"),
left: typeof Expression
left
:
class Expression
Expression
,
right: typeof Expression
right
:
class Expression
Expression
}) {}

Defining recursive schemas where the Encoded type differs from the Type type introduces additional complexity. For instance, if a schema includes fields that transform data (e.g., NumberFromString), the Encoded and Type types may not align.

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:

import {
import Schema
Schema
} from "effect"
class
class Category
Category
extends
import Schema
Schema
.
const Class: <Category>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: ClassAnnotations<Category, Schema.Struct<Fields extends Schema.Struct.Fields>.Type<Fields>> | undefined) => Schema.Class<...>

@example

import { Schema } from "effect"
class MyClass extends Schema.Class<MyClass>("MyClass")({
someField: Schema.String
}) {
someMethod() {
return this.someField + "bar"
}
}

@since3.10.0

Class
<
class Category
Category
>("Category")({
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".

@since3.10.0

NumberFromString
,
name: typeof Schema.String
name
:
import Schema
Schema
.
class String
export String

@since3.10.0

String
,
subcategories: Schema.Array$<Schema.suspend<Category, Category, never>>
subcategories
:
import Schema
Schema
.
Array<Schema.suspend<Category, Category, never>>(value: Schema.suspend<Category, Category, never>): Schema.Array$<Schema.suspend<Category, Category, never>>
export Array

@since3.10.0

Array
(
// @ts-expect-error
import Schema
Schema
.
const suspend: <Category, Category, never>(f: () => Schema.Schema<Category, Category, never>) => Schema.suspend<Category, Category, never>

@since3.10.0

suspend
(():
import Schema
Schema
.
interface Schema<in out A, in out I = A, out R = never>

@since3.10.0

@since3.10.0

Schema
<
class Category
Category
> =>
class Category
Category
)
)
}) {}
/*
Type 'typeof Category' is not assignable to type 'Schema<Category, Category, never>'.
The types of 'Encoded.id' are incompatible between these types.
Type 'string' is not assignable to type 'number'.ts(2322)
*/

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:

Example (Adjusting the Schema with Explicit Encoded Type)

import {
import Schema
Schema
} from "effect"
interface
interface CategoryEncoded
CategoryEncoded
{
readonly
CategoryEncoded.id: string
id
: string
readonly
CategoryEncoded.name: string
name
: string
readonly
CategoryEncoded.subcategories: readonly CategoryEncoded[]
subcategories
:
interface ReadonlyArray<T>
ReadonlyArray
<
interface CategoryEncoded
CategoryEncoded
>
}
class
class Category
Category
extends
import Schema
Schema
.
const Class: <Category>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: ClassAnnotations<Category, Schema.Struct<Fields extends Schema.Struct.Fields>.Type<Fields>> | undefined) => Schema.Class<...>

@example

import { Schema } from "effect"
class MyClass extends Schema.Class<MyClass>("MyClass")({
someField: Schema.String
}) {
someMethod() {
return this.someField + "bar"
}
}

@since3.10.0

Class
<
class Category
Category
>("Category")({
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".

@since3.10.0

NumberFromString
,
name: typeof Schema.String
name
:
import Schema
Schema
.
class String
export String

@since3.10.0

String
,
subcategories: Schema.Array$<Schema.suspend<Category, CategoryEncoded, never>>
subcategories
:
import Schema
Schema
.
Array<Schema.suspend<Category, CategoryEncoded, never>>(value: Schema.suspend<Category, CategoryEncoded, never>): Schema.Array$<...>
export Array

@since3.10.0

Array
(
import Schema
Schema
.
const suspend: <Category, CategoryEncoded, never>(f: () => Schema.Schema<Category, CategoryEncoded, never>) => Schema.suspend<Category, CategoryEncoded, never>

@since3.10.0

suspend
(
():
import Schema
Schema
.
interface Schema<in out A, in out I = A, out R = never>

@since3.10.0

@since3.10.0

Schema
<
class Category
Category
,
interface CategoryEncoded
CategoryEncoded
> =>
class Category
Category
)
)
}) {}

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.

Example (Separating Recursive Field)

import {
import Schema
Schema
} from "effect"
const
const fields: {
id: typeof Schema.NumberFromString;
name: typeof Schema.String;
}
fields
= {
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".

@since3.10.0

NumberFromString
,
name: typeof Schema.String
name
:
import Schema
Schema
.
class String
export String

@since3.10.0

String
// ...possibly other fields
}
interface
interface CategoryEncoded
CategoryEncoded
extends
import Schema
Schema
.
namespace Struct

@since3.10.0

@since3.10.0

@since3.10.0

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<...>; }

@since3.10.0

Encoded
<typeof
const fields: {
id: typeof Schema.NumberFromString;
name: typeof Schema.String;
}
fields
> {
// Define `subcategories` using recursion
readonly
CategoryEncoded.subcategories: readonly CategoryEncoded[]
subcategories
:
interface ReadonlyArray<T>
ReadonlyArray
<
interface CategoryEncoded
CategoryEncoded
>
}
class
class Category
Category
extends
import Schema
Schema
.
const Class: <Category>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: ClassAnnotations<Category, Schema.Struct<Fields extends Schema.Struct.Fields>.Type<Fields>> | undefined) => Schema.Class<...>

@example

import { Schema } from "effect"
class MyClass extends Schema.Class<MyClass>("MyClass")({
someField: Schema.String
}) {
someMethod() {
return this.someField + "bar"
}
}

@since3.10.0

Class
<
class Category
Category
>("Category")({
...
const fields: {
id: typeof Schema.NumberFromString;
name: typeof Schema.String;
}
fields
, // Include the fields
subcategories: Schema.Array$<Schema.suspend<Category, CategoryEncoded, never>>
subcategories
:
import Schema
Schema
.
Array<Schema.suspend<Category, CategoryEncoded, never>>(value: Schema.suspend<Category, CategoryEncoded, never>): Schema.Array$<...>
export Array

@since3.10.0

Array
(
// Define `subcategories` using recursion
import Schema
Schema
.
const suspend: <Category, CategoryEncoded, never>(f: () => Schema.Schema<Category, CategoryEncoded, never>) => Schema.suspend<Category, CategoryEncoded, never>

@since3.10.0

suspend
(
():
import Schema
Schema
.
interface Schema<in out A, in out I = A, out R = never>

@since3.10.0

@since3.10.0

Schema
<
class Category
Category
,
interface CategoryEncoded
CategoryEncoded
> =>
class Category
Category
)
)
}) {}

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

Example (Creating Tagged Classes and Errors)

import {
import Schema
Schema
} from "effect"
// Define a tagged class with a "name" field
class
class TaggedPerson
TaggedPerson
extends
import Schema
Schema
.
const TaggedClass: <TaggedPerson>(identifier?: string) => <Tag, Fields>(tag: Tag, fieldsOr: Fields | HasFields<Fields>, annotations?: ClassAnnotations<TaggedPerson, Schema.Struct<Fields extends Schema.Struct.Fields>.Type<...>> | undefined) => Schema.TaggedClass<...>

@example

import { Schema } from "effect"
class MyClass extends Schema.TaggedClass<MyClass>("MyClass")("MyClass", {
a: Schema.String
}) {}

@since3.10.0

TaggedClass
<
class TaggedPerson
TaggedPerson
>()(
"TaggedPerson",
{
name: typeof Schema.String
name
:
import Schema
Schema
.
class String
export String

@since3.10.0

String
}
) {}
// Define a tagged error with a "status" field
class
class HttpError
HttpError
extends
import Schema
Schema
.
const TaggedError: <HttpError>(identifier?: string) => <Tag, Fields>(tag: Tag, fieldsOr: Fields | HasFields<Fields>, annotations?: ClassAnnotations<HttpError, Schema.Struct<Fields extends Schema.Struct.Fields>.Type<...>> | undefined) => Schema.TaggedErrorClass<...>

@example

import { Schema } from "effect"
class MyError extends Schema.TaggedError<MyError>("MyError")(
"MyError",
{
module: Schema.String,
method: Schema.String,
description: Schema.String
}
) {
get message(): string {
return `${this.module}.${this.method}: ${this.description}`
}
}

@since3.10.0

TaggedError
<
class HttpError
HttpError
>()("HttpError", {
status: typeof Schema.Number
status
:
import Schema
Schema
.
class Number
export Number

@since3.10.0

Number
}) {}
const
const joe: TaggedPerson
joe
= new
constructor TaggedPerson(props: {
readonly name: string;
}, options?: MakeOptions): TaggedPerson
TaggedPerson
({
name: string
name
: "Joe" })
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 and process.stderr. 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 for more information.

Example using the global console:

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:

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

@seesource

console
.
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) (the arguments are all passed to util.format()).

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() for more information.

@sincev0.1.100

log
(
const joe: TaggedPerson
joe
.
_tag: "TaggedPerson"
_tag
)
// Output: "TaggedPerson"
const
const error: HttpError
error
= new
constructor HttpError(props: {
readonly status: number;
}, options?: MakeOptions): HttpError
HttpError
({
status: number
status
: 404 })
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 and process.stderr. 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 for more information.

Example using the global console:

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:

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

@seesource

console
.
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) (the arguments are all passed to util.format()).

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() for more information.

@sincev0.1.100

log
(
const error: HttpError
error
.
_tag: "HttpError"
_tag
)
// Output: "HttpError"
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 and process.stderr. 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 for more information.

Example using the global console:

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:

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

@seesource

console
.
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) (the arguments are all passed to util.format()).

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() for more information.

@sincev0.1.100

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

The extend static utility allows you to enhance an existing schema class by adding additional fields and functionality. This approach helps in building on top of existing schemas without redefining them from scratch.

Example (Extending a Schema Class)

import {
import Schema
Schema
} from "effect"
// Define the base class
class
class Person
Person
extends
import Schema
Schema
.
const Class: <Person>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: ClassAnnotations<Person, Schema.Struct<Fields extends Schema.Struct.Fields>.Type<Fields>> | undefined) => Schema.Class<...>

@example

import { Schema } from "effect"
class MyClass extends Schema.Class<MyClass>("MyClass")({
someField: Schema.String
}) {
someMethod() {
return this.someField + "bar"
}
}

@since3.10.0

Class
<
class Person
Person
>("Person")({
id: typeof Schema.Number
id
:
import Schema
Schema
.
class Number
export Number

@since3.10.0

Number
,
name: typeof Schema.NonEmptyString
name
:
import Schema
Schema
.
class NonEmptyString

@since3.10.0

NonEmptyString
}) {
// A custom getter that converts the name to uppercase
get
Person.upperName: string
upperName
() {
return this.
name: string
name
.
String.toUpperCase(): string

Converts all the alphabetic characters in a string to uppercase.

toUpperCase
()
}
}
// Extend the base class to include an "age" field
class
class PersonWithAge
PersonWithAge
extends
class Person
Person
.
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?: ClassAnnotations<PersonWithAge, Schema.Struct<Fields extends Schema.Struct.Fields>.Type<...>> | undefined) => Schema.Class<...>

@example

import { Schema } from "effect"
class MyClass extends Schema.Class<MyClass>("MyClass")({
myField: Schema.String
}) {
myMethod() {
return this.myField + "my"
}
}
class NextClass extends MyClass.extend<NextClass>("NextClass")({
nextField: Schema.Number
}) {
nextMethod() {
return this.myMethod() + this.myField + this.nextField
}
}

extend
<
class PersonWithAge
PersonWithAge
>("PersonWithAge")(
{
age: typeof Schema.Number
age
:
import Schema
Schema
.
class Number
export Number

@since3.10.0

Number
}
) {
// A custom getter to check if the person is an adult
get
PersonWithAge.isAdult: boolean
isAdult
() {
return this.
age: number
age
>= 18
}
}
// Usage
const
const john: PersonWithAge
john
= new
constructor PersonWithAge(props: {
readonly id: number;
readonly name: string;
readonly age: number;
}, options?: MakeOptions): PersonWithAge
PersonWithAge
({
id: number
id
: 1,
name: string
name
: "John",
age: number
age
: 25 })
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 and process.stderr. 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 for more information.

Example using the global console:

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:

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

@seesource

console
.
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) (the arguments are all passed to util.format()).

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() for more information.

@sincev0.1.100

log
(
const john: PersonWithAge
john
.
Person.upperName: string
upperName
) // Output: "JOHN"
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 and process.stderr. 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 for more information.

Example using the global console:

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:

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

@seesource

console
.
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) (the arguments are all passed to util.format()).

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() for more information.

@sincev0.1.100

log
(
const john: PersonWithAge
john
.
PersonWithAge.isAdult: boolean
isAdult
) // Output: true

Note that you can only add additional fields when extending a class.

Example (Attempting to Overwrite Existing Fields)

import {
import Schema
Schema
} from "effect"
class
class Person
Person
extends
import Schema
Schema
.
const Class: <Person>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: ClassAnnotations<Person, Schema.Struct<Fields extends Schema.Struct.Fields>.Type<Fields>> | undefined) => Schema.Class<...>

@example

import { Schema } from "effect"
class MyClass extends Schema.Class<MyClass>("MyClass")({
someField: Schema.String
}) {
someMethod() {
return this.someField + "bar"
}
}

@since3.10.0

Class
<
class Person
Person
>("Person")({
id: typeof Schema.Number
id
:
import Schema
Schema
.
class Number
export Number

@since3.10.0

Number
,
name: typeof Schema.NonEmptyString
name
:
import Schema
Schema
.
class NonEmptyString

@since3.10.0

NonEmptyString
}) {
get
Person.upperName: string
upperName
() {
return this.
name: string
name
.
String.toUpperCase(): string

Converts all the alphabetic characters in a string to uppercase.

toUpperCase
()
}
}
class
class BadExtension
BadExtension
extends
class Person
Person
.
Class<Person, { id: typeof Number$; name: typeof NonEmptyString; }, Struct<Fields extends Struct.Fields>.Encoded<{ id: typeof Number$; name: typeof NonEmptyString; }>, never, { ...; } & { ...; }, {}, {}>.extend<BadExtension>(identifier: string): <NewFields>(fields: NewFields | HasFields<NewFields>, annotations?: ClassAnnotations<BadExtension, Schema.Struct<Fields extends Schema.Struct.Fields>.Type<...>> | undefined) => Schema.Class<...>

@example

import { Schema } from "effect"
class MyClass extends Schema.Class<MyClass>("MyClass")({
myField: Schema.String
}) {
myMethod() {
return this.myField + "my"
}
}
class NextClass extends MyClass.extend<NextClass>("NextClass")({
nextField: Schema.Number
}) {
nextMethod() {
return this.myMethod() + this.myField + this.nextField
}
}

extend
<
class BadExtension
BadExtension
>("BadExtension")({
name: typeof Schema.Number
name
:
import Schema
Schema
.
class Number
export Number

@since3.10.0

Number
}) {}
/*
throws:
Error: Duplicate property signature
details: Duplicate key "name"
*/

This error occurs because allowing fields to be overwritten is not safe. It could interfere with any getters or methods defined on the class that rely on the original definition. For example, in this case, the upperName getter would break if the name field was changed to a number.

You can enhance schema classes with effectful transformations to enrich or validate entities, particularly when working with data sourced from external systems like databases or APIs.

Example (Effectful Transformation)

The following example demonstrates adding an age field to a Person class. The age value is derived asynchronously based on the id field.

import {
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
,
import Option

@since2.0.0

@since2.0.0

Option
,
import Schema
Schema
,
import ParseResult
ParseResult
} from "effect"
// Base class definition
class
class Person
Person
extends
import Schema
Schema
.
const Class: <Person>(identifier: string) => <Fields>(fieldsOr: Fields | HasFields<Fields>, annotations?: ClassAnnotations<Person, Schema.Struct<Fields extends Schema.Struct.Fields>.Type<Fields>> | undefined) => Schema.Class<...>

@example

import { Schema } from "effect"
class MyClass extends Schema.Class<MyClass>("MyClass")({
someField: Schema.String
}) {
someMethod() {
return this.someField + "bar"
}
}

@since3.10.0

Class
<
class Person
Person
>("Person")({
id: typeof Schema.Number
id
:
import Schema
Schema
.
class Number
export Number

@since3.10.0

Number
,
name: typeof Schema.String
name
:
import Schema
Schema
.
class String
export String

@since3.10.0

String
}) {}
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 and process.stderr. 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 for more information.

Example using the global console:

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:

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

@seesource

console
.
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) (the arguments are all passed to util.format()).

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() for more information.

@sincev0.1.100

log
(
import Schema
Schema
.
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

@throwsParseError

@since3.10.0

decodeUnknownSync
(
class Person
Person
)({
id: number
id
: 1,
name: string
name
: "name" }))
/*
Output:
Person { id: 1, name: 'name' }
*/
// Simulate fetching age asynchronously based on id
function
function getAge(id: number): Effect.Effect<number, Error>
getAge
(
id: number
id
: number):
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
interface Effect<out A, out E = never, out R = never>

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.

@since2.0.0

@since2.0.0

Effect
<number,
interface Error
Error
> {
return
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

Effect
.
const succeed: <number>(value: number) => Effect.Effect<number, never, never>

Creates an Effect that always succeeds with a given value.

When to Use

Use this function when you need an effect that completes successfully with a specific value without any errors or external dependencies.

@seefail to create an effect that represents a failure.

@example

// Title: Creating a Successful Effect
import { Effect } from "effect"
// Creating an effect that represents a successful scenario
//
// ┌─── Effect<number, never, never>
// ▼
const success = Effect.succeed(42)

@since2.0.0

succeed
(
id: number
id
+ 2)
}
// Extended class with a transformation
class
class PersonWithTransform
PersonWithTransform
extends
class Person
Person
.
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?: ClassAnnotations<...> | undefined) => Schema.Class<...>

@example

import { Effect, Schema } from "effect"
class MyClass extends Schema.Class<MyClass>("MyClass")({
myField: Schema.String
}) {
myMethod() {
return this.myField + "my"
}
}
class NextClass extends MyClass.transformOrFail<NextClass>("NextClass")({
nextField: Schema.Number
}, {
decode: (i) =>
Effect.succeed({
myField: i.myField,
nextField: i.myField.length
}),
encode: (a) => Effect.succeed({ myField: a.myField })
}) {
nextMethod() {
return this.myMethod() + this.myField + this.nextField
}
}

transformOrFail
<
class PersonWithTransform
PersonWithTransform
>(
"PersonWithTransform"
)(
{
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)

@since3.10.0

optionalWith
(
import Schema
Schema
.
class Number
export Number

@since3.10.0

Number
, {
exact: true
exact
: true,
as: "Option"
as
: "Option" })
},
{
// Decoding logic for the new field
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
: (
input: {
readonly id: number;
readonly name: string;
}
input
) =>
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

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)

The mapBoth function allows you to apply transformations to both the error and success channels of an effect.

This function takes two map functions as arguments: one for the error channel and one for the success channel. You can use it when you want to modify both the error and the success values without altering the overall success or failure status of the effect.

@seemap for a version that operates on the success channel.

@seemapError for a version that operates on the error channel.

@example

import { Effect } from "effect"
// ┌─── Effect<number, string, never>
// ▼
const simulatedTask = Effect.fail("Oh no!").pipe(Effect.as(1))
// ┌─── Effect<boolean, Error, never>
// ▼
const modified = Effect.mapBoth(simulatedTask, {
onFailure: (message) => new Error(message),
onSuccess: (n) => n > 0
})

@since2.0.0

mapBoth
(
function getAge(id: number): Effect.Effect<number, Error>
getAge
(
input: {
readonly id: number;
readonly name: string;
}
input
.
id: number
id
), {
onFailure: (e: Error) => ParseResult.Type
onFailure
: (
e: Error
e
) =>
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.

@since3.10.0

Type
(
import Schema
Schema
.
class String
export String

@since3.10.0

String
.
Schema<in out A, in out I = A, out R = never>.ast: AST
ast
,
input: {
readonly id: number;
readonly name: string;
}
input
.
id: number
id
,
e: Error
e
.
Error.message: string
message
),
// Must return { age: Option<number> }
onSuccess: (a: number) => {
age: Option.Option<number>;
id: number;
name: string;
}
onSuccess
: (
age: number
age
) => ({ ...
input: {
readonly id: number;
readonly name: string;
}
input
,
age: Option.Option<number>
age
:
import Option

@since2.0.0

@since2.0.0

Option
.
const some: <number>(value: number) => Option.Option<number>

Creates a new Option that wraps the given value.

@paramvalue - The value to wrap.

@since2.0.0

some
(
age: number
age
) })
}),
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>

@since3.10.0

succeed
}
) {}
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<...>

@since3.10.0

decodeUnknownPromise
(
class PersonWithTransform
PersonWithTransform
)({
id: number
id
: 1,
name: string
name
: "name"
}).
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.

@paramonfulfilled The callback to execute when the Promise is resolved.

@paramonrejected The callback to execute when the Promise is rejected.

@returnsA Promise for the completion of which ever callback is executed.

then
(
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 and process.stderr. 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 for more information.

Example using the global console:

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:

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

@seesource

console
.
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) (the arguments are all passed to util.format()).

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() for more information.

@sincev0.1.100

log
)
/*
Output:
PersonWithTransform {
id: 1,
name: 'name',
age: { _id: 'Option', _tag: 'Some', value: 3 }
}
*/
// Extended class with a conditional Transformation
class
class PersonWithTransformFrom
PersonWithTransformFrom
extends
class Person
Person
.
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?: ClassAnnotations<...> | undefined) => Schema.Class<...>

@example

import { Effect, Schema } from "effect"
class MyClass extends Schema.Class<MyClass>("MyClass")({
myField: Schema.String
}) {
myMethod() {
return this.myField + "my"
}
}
class NextClass extends MyClass.transformOrFailFrom<NextClass>("NextClass")({
nextField: Schema.Number
}, {
decode: (i) =>
Effect.succeed({
myField: i.myField,
nextField: i.myField.length
}),
encode: (a) => Effect.succeed({ myField: a.myField })
}) {
nextMethod() {
return this.myMethod() + this.myField + this.nextField
}
}

transformOrFailFrom
<
class PersonWithTransformFrom
PersonWithTransformFrom
>(
"PersonWithTransformFrom"
)(
{
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)

@since3.10.0

optionalWith
(
import Schema
Schema
.
class Number
export Number

@since3.10.0

Number
, {
exact: true
exact
: true,
as: "Option"
as
: "Option" })
},
{
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
: (
input: {
readonly id: number;
readonly name: string;
}
input
) =>
import Effect

@since2.0.0

@since2.0.0

@since2.0.0

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)

The mapBoth function allows you to apply transformations to both the error and success channels of an effect.

This function takes two map functions as arguments: one for the error channel and one for the success channel. You can use it when you want to modify both the error and the success values without altering the overall success or failure status of the effect.

@seemap for a version that operates on the success channel.

@seemapError for a version that operates on the error channel.

@example

import { Effect } from "effect"
// ┌─── Effect<number, string, never>
// ▼
const simulatedTask = Effect.fail("Oh no!").pipe(Effect.as(1))
// ┌─── Effect<boolean, Error, never>
// ▼
const modified = Effect.mapBoth(simulatedTask, {
onFailure: (message) => new Error(message),
onSuccess: (n) => n > 0
})

@since2.0.0

mapBoth
(
function getAge(id: number): Effect.Effect<number, Error>
getAge
(
input: {
readonly id: number;
readonly name: string;
}
input
.
id: number
id
), {
onFailure: (e: Error) => ParseResult.Type
onFailure
: (
e: Error
e
) =>
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.

@since3.10.0

Type
(
import Schema
Schema
.
class String
export String

@since3.10.0

String
.
Schema<in out A, in out I = A, out R = never>.ast: AST
ast
,
input: {
readonly id: number;
readonly name: string;
}
input
,
e: Error
e
.
Error.message: string
message
),
// Must return { age?: number }
onSuccess: (a: number) => {
age: number;
id: number;
name: string;
} | {
id: number;
name: string;
}
onSuccess
: (
age: number
age
) => (
age: number
age
> 18 ? { ...
input: {
readonly id: number;
readonly name: string;
}
input
,
age: number
age
} : { ...
input: {
readonly id: number;
readonly name: string;
}
input
})
}),
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>

@since3.10.0

succeed
}
) {}
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<...>

@since3.10.0

decodeUnknownPromise
(
class PersonWithTransformFrom
PersonWithTransformFrom
)({
id: number
id
: 1,
name: string
name
: "name"
}).
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.

@paramonfulfilled The callback to execute when the Promise is resolved.

@paramonrejected The callback to execute when the Promise is rejected.

@returnsA Promise for the completion of which ever callback is executed.

then
(
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 and process.stderr. 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 for more information.

Example using the global console:

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:

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

@seesource

console
.
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) (the arguments are all passed to util.format()).

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() for more information.

@sincev0.1.100

log
)
/*
Output:
PersonWithTransformFrom {
id: 1,
name: 'name',
age: { _id: 'Option', _tag: 'None' }
}
*/

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 Schema.optionalWith(Schema.Number, { exact: true, as: "Option" }) is executed.
    • This approach allows for immediate handling of the input, potentially influencing the subsequent transformations.