Schema encoding

Other schema libraries allow only to decode data (zod comes to mind):

import { z } from "zod";

const Author = z.object({
  name: z.string(),
  age: z.number(),
});

const author = Author.parse(someData);

In this example parse allows to verify that someData conforms to the Author schema. Since there is no input/output transformation in Author, encoding is not that useful.

See however what happens here:

const Author = z.object({
  name: z.string(),
  age: z.string().transform((ageString) => Number(ageString)),
});

By using transform the type of age is different from input (string) to output (number). When we parse on this new Author schema we get { name: string; age: number; }.

What if we need to encode back to the original shape { name: string; age: string; }?

No easy solution at the moment with zod.

Schema encoding

The unique feature of Schema that makes it stand apart from other schema libraries is encoding.

In fact, Schema includes out-of-the-box APIs to convert between types. The same Author schema looks like this:

import { Schema } from "effect";

const Author = Schema.Struct({
  name: Schema.String,
  age: Schema.NumberFromString,
});

With Schema.decodeSync we achieve the same as parse in zod:

/// 👇 { readonly name: string; readonly age: number; }
const authorDecoded = Schema.decodeSync(Author)({ age: "26", name: "Sandro" });

What if we now want to do the inverse? Schema.encodeSync is the answer:

const authorDecoded = Schema.decodeSync(Author)({ age: "26", name: "Sandro" });

/// 👇 { readonly name: string; readonly age: string; }
const authorEncoded = Schema.encodeSync(Author)(authorDecoded);

When to encode data

When is encoding needed?

When we decode a schema the goal is usually to verify and parse some primitive value (for example a JSON response) to an internal representation that works for our app.

Think of decoding as some data coming from outside to the inside.

Often times the decoded schema contains non-serializable values (Map, Set, class).

When we then want to send the data back we need the inverse process: encoding. We convert non-serializable values to a format that can be sent to an external service.

Think of encoding as some data going from inside to the outside.

Schema offers an API specifically designed for all the steps since it includes both decoding and encoding in one single schema definition.