Skip to content

Commit e45e61b

Browse files
committed
Improve codec docs
1 parent 10cc994 commit e45e61b

File tree

2 files changed

+31
-35
lines changed

2 files changed

+31
-35
lines changed

packages/docs/content/codecs.mdx

Lines changed: 19 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -7,41 +7,28 @@ import { ThemedImage } from "@/components/themed-image";
77

88
> **New** — Introduced in `[email protected]`
99
10-
> **TLDR** — You can use `z.encode(<schema>, <input>)` to perform an _encode_ operation ("reverse parsing"). This will work with any schema (except those containing `.transform()`) but is primarily intended for use in conjunction with `z.codec()`.
10+
All Zod schemas can process inputs in both the forward and backward direction:
1111

12-
Zod schemas are "codecs". That is, they can process inputs in both the forward and backward direction:
12+
- **Forward**: `Input` to `Output`
13+
- `.parse()`
14+
- `.decode()`
15+
- **Backward**: `Output` to `Input`
16+
- `.encode()`
1317

14-
- *Decoding*: the "forward" direction: `Input -> Output`. This is what regular `.parse()` does.
15-
- *Encoding*: the "backward" direction: `Output -> Input`.
16-
17-
The regular `.parse()` method performs a *decode* operation (forward direction).
18+
In most cases, this is a distinction without a difference. The input and output types are identical, so there's no difference between "forward" and "backward".
1819

1920
```ts
20-
import * as z from "zod";
21-
22-
const mySchema = z.string();
21+
const schema = z.string();
2322

24-
// method form
25-
mySchema.parse("hello"); // => "hello"
23+
type Input = z.input<typeof schema>; // string
24+
type Output = z.output<typeof schema>; // string
2625

27-
// functional form
28-
z.parse(mySchema, "hello"); // => "hello"
26+
schema.parse("asdf"); // => "asdf"
27+
schema.decode("asdf"); // => "asdf"
28+
schema.encode("asdf"); // => "asdf"
2929
```
3030

31-
For explicitness, Zod provides dedicated functions for performing "decode" and "encode" operations.
32-
33-
```ts
34-
z.decode(mySchema, "hello"); // => "hello"
35-
z.encode(mySchema, "hello"); // => "hello"
36-
```
37-
38-
In many cases (such as the string schema above), the input and output types of a Zod schema are identical, so `z.decode()` and `z.encode()` are functionally equivalent. But some schema types cause the input and output types to diverge:
39-
40-
- `z.default()` (input is optional, output is not)
41-
- `z.transform()` (a unidirectional transformation)
42-
- `z.codec()` (bidirectional transformation)
43-
44-
Most important of these is `z.codec()`, which is Zod's primary mechanism for defining bidirectional transformations.
31+
However, some schema types cause the input and output types to diverge, notably `z.codec()`. Codecs are a special type of schema that defines a *bi-directional transformation* between two other schemas.
4532

4633
```ts
4734
const stringToDate = z.codec(
@@ -52,20 +39,17 @@ const stringToDate = z.codec(
5239
encode: (date) => date.toISOString(), // Date → ISO string
5340
}
5441
);
55-
56-
type Input = z.input<typeof stringToDate>; // => string
57-
type Output = z.output<typeof stringToDate>; // => Date
5842
```
5943

6044
In these cases, `z.decode()` and `z.encode()` behave quite differently.
6145

6246
```ts
6347
const payloadSchema = z.object({ startDate: stringToDate });
6448

65-
z.decode(stringToDate, "2024-01-15T10:30:00.000Z")
49+
stringToDate.decode("2024-01-15T10:30:00.000Z")
6650
// => Date
6751

68-
z.encode(stringToDate, new Date("2024-01-15T10:30:00.000Z"))
52+
stringToDate.encode(new Date("2024-01-15T10:30:00.000Z"))
6953
// => string
7054
```
7155

@@ -79,14 +63,14 @@ This is particularly useful when parsing data at a network boundary. You can sha
7963
alt="Codecs encoding and decoding data across a network boundary"
8064
/>
8165

82-
## Composability
66+
### Composability
8367

8468
> **Note** — You can use `z.encode()` and `z.decode()` with any schema. It doesn't have to be a ZodCodec.
8569
8670
Codecs are a schema like any other. You can nest them inside objects, arrays, pipes, etc. There are no rules on where you can use them!
8771

8872

89-
## Type-safe inputs
73+
### Type-safe inputs
9074

9175
The usual `.parse()` method accepts `unknown` as input, and returns a value that matches the schema's inferred *output type*.
9276

@@ -110,7 +94,7 @@ Here's a diagram demonstrating the differences between the type signatures for `
11094
alt="Codec directionality diagram showing bidirectional transformation between input and output schemas"
11195
/>
11296

113-
## Async and safe variants
97+
### Async and safe variants
11498

11599
As with `.transform()` and `.refine()`, codecs support async transforms.
116100

play.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
11
import * as z from "zod";
22

33
z;
4+
5+
const stringToDate = z.codec(
6+
z.iso.datetime(), // input schema: ISO string
7+
z.date(), // output schema: Date object
8+
{
9+
decode: (isoString) => new Date(isoString), // string → Date
10+
encode: (date) => date.toISOString(), // Date → string
11+
}
12+
);
13+
14+
console.log(stringToDate.decode("2024-01-15T10:30:00.000Z")); // Date
15+
console.log(stringToDate.encode(new Date("2024-01-15"))); // "2024-01-15T00:00:00.000Z"

0 commit comments

Comments
 (0)