Skip to content

Commit

Permalink
feat: support catchall
Browse files Browse the repository at this point in the history
  • Loading branch information
brettz9 committed Jul 1, 2024
1 parent 3958142 commit ddbd214
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 9 deletions.
20 changes: 14 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,14 @@ options:
## Options
Both `zerialize` and `dezerialize` accept an options object with the same properties.
Both `zerialize` and `dezerialize` accept an options object with the
same properties.

Since Zod does not allow the specification of the names of effects (refinements, transforms, and preprocesses), we allow you to supply as options maps of names to effects so that these can be part of serialization and deserialization. Note that due to technical limitations, we cannot support the regular `refine()` method (and it will be ignored) but `superRefine()` is supported. If none of these options are supplied,
the effects will be omitted.
Since Zod does not allow the specification of the names of effects
(refinements, transforms, and preprocesses), we allow you to supply
as options maps of names to effects so that these can be part of
serialization and deserialization. If none of these options are
supplied, the effects will be omitted.

Properties:

Expand All @@ -109,6 +113,10 @@ by this library (any property could be targeted by one's references).

## Caveats

- lazy and brand are omitted
- pipeline and catch types are unwrapped
- native enums are turned into enums
- `brand` is not supportable and omitted
- `lazy`, `pipeline` and `catch` types are unwrapped
- native enums are turned into `enum`s
- Due to technical limitations, we cannot support the regular
`refine()`, `custom()` and `instanceof` methods (and they will be
ignored), but these are really just implementations of `superRefine()`
which is supported
4 changes: 3 additions & 1 deletion src/dezerialize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,9 @@ const dezerializers = {
}
>;

if (shape.unknownKeys === "strict") {
if (shape.catchall) {
i = i.catchall(d(shape.catchall, opts));
} else if (shape.unknownKeys === "strict") {
i = i.strict();
} else if (shape.unknownKeys === "passthrough") {
i = i.passthrough();
Expand Down
11 changes: 11 additions & 0 deletions src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,17 @@ test.each([
},
},
}),
p(z.object({ name: z.string() }).catchall(z.number()), {
type: "object",
properties: {
name: {
type: "string",
},
},
catchall: {
type: "number",
},
}),
p(z.number().catch(42), { type: "number" }),

p(z.string(), { type: "string" }),
Expand Down
7 changes: 7 additions & 0 deletions src/schema.zodex
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,13 @@
},
"isOptional": true
},
"catchall": {
"type": "union",
"options": [{
"$ref": "#/$defs/reference-or-type"
}],
"isOptional": true
},
"unknownKeys": {
"type": "enum",
"values": ["strict", "strip", "passthrough"],
Expand Down
6 changes: 4 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,13 @@ export type SzArray<T extends SzType = SzType> = {
maxLength?: number;
};
export type SzObject<
T extends Record<string, SzType> = Record<string, SzType>
T extends Record<string, SzType> = Record<string, SzType>,
U extends SzType = SzType
> = {
type: "object";
properties?: T;
unknownKeys?: "strict" | "strip" | "passthrough";
catchall?: U;
};

export type SzUnion<Options extends [SzType, ...SzType[]] = [SzType]> = {
Expand Down Expand Up @@ -210,7 +212,7 @@ export type SzType = (
| SzPrimitive
| SzLiteral<any>
| SzArray<any>
| SzObject<any>
| SzObject<any, any>
| SzUnion<any>
| SzDiscriminatedUnion<any, any>
| SzIntersection<any, any>
Expand Down
8 changes: 8 additions & 0 deletions src/zerialize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,14 @@ const zerializers = {

return {
type: "object",
...(def.catchall._def.typeName === "ZodNever"
? {}
: {
catchall: s(def.catchall, {
...opts,
paths: [...opts.paths, "catchall"],
}),
}),
...(def.unknownKeys === "strip"
? {}
: {
Expand Down

0 comments on commit ddbd214

Please sign in to comment.