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.