# Schema

`Schema` lets you describe the shape of your data once and reuse that single
description for everything you would otherwise write by hand: validating unknown
input, decoding it into typed values, encoding those values back into a
serializable form, generating JSON Schema, deriving equivalence, and producing
test data.

A schema is a value, not a type. Every schema carries two views of your data:

- the decoded **Type** — the value you work with in your program (e.g. a `Date`,
  a branded `UserId`, a class instance), and
- the **Encoded** representation — the serialized form that crosses a boundary
  (e.g. the ISO string in a JSON payload).

```ts
import { Schema } from "effect"

// A single description of a user. `name` and `age` are required;
// `email` is an exact-optional key (it may be omitted entirely).
const User = Schema.Struct({
  name: Schema.String.check(Schema.isMinLength(1)),
  age: Schema.Number.check(Schema.isGreaterThanOrEqualTo(0)),
  email: Schema.optionalKey(Schema.String)
})

// Decode unknown external input into a validated value. Throws on failure.
const user = Schema.decodeUnknownSync(User)({ name: "Alice", age: 30 })

console.log(user)
// { name: "Alice", age: 30 }
```

The same `User` schema can decode, encode, validate, act as a type guard, and
generate a JSON Schema document — you never define the shape more than once.

## Mental model

- **Schema** — a description of a data shape. Most concrete schemas are
  **codecs**: they track both `Type` and `Encoded`, so they decode *and* encode.
- **Decoding** — turning unknown external data (API responses, form
  submissions, config files) into typed, validated values.
- **Encoding** — turning typed values back into a serializable format.
- **Check (filter)** — a constraint attached to a schema with `.check(...)`,
  such as `Schema.isMinLength(1)` or `Schema.isGreaterThan(0)`.
- **Transformation** — a decode/encode pair that converts between two schemas,
  created with `Schema.decodeTo` / `Schema.encodeTo`.
- **Annotation** — metadata (title, description, custom keys) attached with
  `.annotate(...)`.

## In this section

- [Basic usage](https://effect.plants.sh/schema/basic-usage/) — decode and encode, the sync/Effect
  variants, and the two type parameters every schema carries.
- [Primitives](https://effect.plants.sh/schema/primitives/) — primitive schemas, literals, and unions.
- [Structs and records](https://effect.plants.sh/schema/structs-and-records/) — objects, dictionaries,
  arrays, tuples, and optional/mutable fields.
- [Filters](https://effect.plants.sh/schema/filters/) — refine values with built-in and custom checks.
- [Transformations](https://effect.plants.sh/schema/transformations/) — convert between encoded and
  decoded representations.
- [Classes](https://effect.plants.sh/schema/classes/) — `Schema.Class` for data types with methods and
  value-based identity.
- [Error formatting](https://effect.plants.sh/schema/error-formatting/) — inspect and format decode
  failures.
- [Defining errors](https://effect.plants.sh/schema/defining-errors/) — tagged, schema-backed errors
  with `Schema.TaggedErrorClass`.
- [JSON Schema](https://effect.plants.sh/schema/json-schema/) — generate a JSON Schema document from a
  schema.

Schema is used throughout Effect: [Configuration](https://effect.plants.sh/configuration/) for typed
config, the [HTTP API](https://effect.plants.sh/http-api/) for request/response contracts, [RPC](https://effect.plants.sh/rpc/)
and [Cluster](https://effect.plants.sh/cluster/) for serializable messages, and [SQL](https://effect.plants.sh/sql/) for row
shapes.