
Product
Introducing Webhook Events for Alert Changes
Add real-time Socket webhook events to your workflows to automatically receive software supply chain alert changes in real time.
@effect/schema
Advanced tools
Welcome to the documentation for @effect/schema, a library for defining and using schemas to validate and transform data in TypeScript.
@effect/schema allows you to define a Schema<Type, Encoded, Context> that provides a blueprint for describing the structure and data types of your data. Once defined, you can leverage this schema to perform a range of operations, including:
| Operation | Description |
|---|---|
| Decoding | Transforming data from an input type Encoded to an output type Type. |
| Encoding | Converting data from an output type Type back to an input type Encoded. |
| Asserting | Verifying that a value adheres to the schema's output type Type. |
| Arbitraries | Generate arbitraries for fast-check testing. |
| JSON Schemas | Create JSON Schemas based on defined schemas. |
| Equivalence | Create Equivalences based on defined schemas. |
| Pretty printing | Support pretty printing for data structures. |
strict flag enabled in your tsconfig.json fileexactOptionalPropertyTypes flag enabled in your tsconfig.json file
{
// ...
"compilerOptions": {
// ...
"strict": true,
"exactOptionalPropertyTypes": true
}
}
effect package (peer dependency)To install the beta version:
npm install @effect/schema
Additionally, make sure to install the effect package, as it's peer dependencies. Note that some package managers might not install peer dependencies by default, so you need to install them manually.
Once you have installed the library, you can import the necessary types and functions from the @effect/schema/Schema module.
Example (Namespace Import)
import * as Schema from "@effect/schema/Schema"
Example (Named Import)
import { Schema } from "@effect/schema"
A schema is a description of a data structure that can be used to generate various artifacts from a single declaration.
From a technical point of view a schema is just a typed wrapper of an AST value:
interface Schema<A, I, R> {
readonly ast: AST
}
The AST type represents a tiny portion of the TypeScript AST, roughly speaking the part describing ADTs (algebraic data types),
i.e. products (like structs and tuples) and unions, plus a custom transformation node.
This means that you can define your own schema constructors / combinators as long as you are able to manipulate the AST value accordingly, let's see an example.
Say we want to define a pair schema constructor, which takes a Schema<A, I, R> as input and returns a Schema<readonly [A, A], readonly [I, I], R> as output.
First of all we need to define the signature of pair
import type { Schema } from "@effect/schema"
declare const pair: <A, I, R>(
schema: Schema.Schema<A, I, R>
) => Schema.Schema<readonly [A, A], readonly [I, I], R>
Then we can implement the body using the APIs exported by the @effect/schema/AST module:
import { AST, Schema } from "@effect/schema"
const pair = <A, I, R>(
schema: Schema.Schema<A, I, R>
): Schema.Schema<readonly [A, A], readonly [I, I], R> => {
const element = new AST.OptionalType(
schema.ast, // <= the element type
false // <= is optional?
)
const tuple = new AST.TupleType(
[element, element], // <= elements definitions
[], // <= rest element
true // <= is readonly?
)
return Schema.make(tuple) // <= wrap the AST value in a Schema
}
This example demonstrates the use of the low-level APIs of the AST module, however, the same result can be achieved more easily and conveniently by using the high-level APIs provided by the Schema module.
import { Schema } from "@effect/schema"
const pair = <A, I, R>(
schema: Schema.Schema<A, I, R>
): Schema.Schema<readonly [A, A], readonly [I, I], R> =>
Schema.Tuple(schema, schema)
If your needs aren't addressed by the existing built-in APIs, you have the option to craft your own API using the built-in APIs as a foundation. If these still don't suffice, you can delve into the lower-level APIs provided by the @effect/schema/AST module.
To develop a robust custom API, you need to address two primary challenges:
Schema or AST module APIs?Let's explore a practical example: "Is it possible to make all fields of a struct nullable?"
Defining the API Signature in TypeScript
First, let's determine if we can define the API's TypeScript signature:
import { Schema } from "@effect/schema"
declare const nullableFields: <
Fields extends { readonly [x: string]: Schema.Schema.Any }
>(
schema: Schema.Struct<Fields>
) => Schema.Struct<{ [K in keyof Fields]: Schema.NullOr<Fields[K]> }>
// Example use
/*
const schema: Schema.Struct<{
name: Schema.NullOr<typeof Schema.String>;
age: Schema.NullOr<typeof Schema.Number>;
}>
*/
const schema = nullableFields(
Schema.Struct({
name: Schema.String,
age: Schema.Number
})
)
You can preliminarily define the signature of nullableFields using TypeScript's declare keyword, allowing you to immediately test its validity (at the type-level, initially). The example above confirms that the API behaves as expected by inspecting a schema that utilizes this new API.
const schema: Schema.Struct<{
name: Schema.NullOr<typeof Schema.String>
age: Schema.NullOr<typeof Schema.Number>
}>
Implementing the API at Runtime
import { Schema } from "@effect/schema"
import { Record } from "effect"
const nullableFields = <
Fields extends { readonly [x: string]: Schema.Schema.Any }
>(
schema: Schema.Struct<Fields>
): Schema.Struct<{ [K in keyof Fields]: Schema.NullOr<Fields[K]> }> => {
return Schema.Struct(
Record.map(schema.fields, (schema) => Schema.NullOr(schema)) as any as {
[K in keyof Fields]: Schema.NullOr<Fields[K]>
}
)
}
const schema = nullableFields(
Schema.Struct({
name: Schema.String,
age: Schema.Number
})
)
console.log(Schema.decodeUnknownSync(schema)({ name: "a", age: null }))
/*
Output:
{ name: 'a', age: null }
*/
This library was inspired by the following projects:
By contributing to this project, you agree that your contributions will be licensed under the project's MIT License.
Thank you for considering contributing to our project! Here are some guidelines to help you get started:
If you have found a bug, please open an issue on our issue tracker and provide as much detail as possible. This should include:
If you have an idea for an enhancement or a new feature, please open an issue on our issue tracker and provide as much detail as possible. This should include:
We welcome contributions via pull requests! Here are some guidelines to help you get started:
git checkout -b my-new-featurepnpm install (assuming pnpm version 8.x).pnpm check: Verify that the code compiles.pnpm test: Execute the tests.pnpm circular: Confirm there are no circular imports.pnpm lint: Check for code style adherence (if you happen to encounter any errors during this process, you can add the --fix option to automatically fix some of these style issues).pnpm dtslint: Run type-level tests.pnpm docgen: Update the automatically generated documentation.pnpm changeset.git commit -am 'Add some feature'.git push origin my-new-feature.main branch.Yup is a JavaScript schema builder for value parsing and validation. It is similar to @effect/schema in that it allows you to define schemas and validate data. However, Yup is more widely used and has a larger community.
Joi is a powerful schema description language and data validator for JavaScript. Like @effect/schema, it allows you to define and validate schemas. Joi is known for its extensive feature set and flexibility.
Zod is a TypeScript-first schema declaration and validation library. It is similar to @effect/schema in its focus on TypeScript integration and type safety. Zod is known for its simplicity and ease of use.
FAQs
Modeling the schema of data structures as first-class values
The npm package @effect/schema receives a total of 822,972 weekly downloads. As such, @effect/schema popularity was classified as popular.
We found that @effect/schema demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Product
Add real-time Socket webhook events to your workflows to automatically receive software supply chain alert changes in real time.

Security News
ENISA has become a CVE Program Root, giving the EU a central authority for coordinating vulnerability reporting, disclosure, and cross-border response.

Product
Socket now scans OpenVSX extensions, giving teams early detection of risky behaviors, hidden capabilities, and supply chain threats in developer tools.