AOT compiler for Zod 4 schemas that generates fast property-stripping functions. Port of exact-mirror from TypeBox to Zod 4.
| 1 | bun add exact-mirror-zod |
Requires Zod 4.
| 1 | import { z } from "zod"; |
| 2 | import { createMirror } from "exact-mirror-zod"; |
| 3 | |
| 4 | const schema = z.object({ name: z.string(), age: z.number() }); |
| 5 | const mirror = createMirror(schema); |
| 6 | |
| 7 | mirror({ name: "test", age: 25, password: "leaked" }); |
| 8 | // => { name: "test", age: 25 } |
createMirror(schema) compiles a Zod schema into a function that strips unknown properties from objects to match the schema's shape. It does not validate -- it assumes input is already valid and just projects known keys.
Validate on input (z.parse()), strip on output (createMirror()). Prevents leaking internal fields from API responses without the overhead of full re-parsing. Typically 5-15x faster than z.parse() for stripping.
| Type | Behavior |
|---|---|
| Object | Keeps only declared keys |
| Array | Per-element mirroring (passes through primitive arrays) |
| Tuple | Per-index mirroring |
| Record | Object.keys iteration with value mirroring |
| Discriminated Union | switch on discriminator key |
| Union | Cheap typeof / Array.isArray structural checks |
| Intersection | Merges object shapes |
Recursive (z.lazy) | Memoized helpers with cycle detection |
| Wrappers | optional, nullable, default, readonly, branded, pipe -- unwraps and recurses |
| 1 | createMirror(schema, { |
| 2 | // Sanitization functions applied to every string value |
| 3 | sanitize: (v) => v.trim(), |
| 4 | |
| 5 | // Max recursion depth for z.lazy() schemas (default: 8) |
| 6 | recursionLimit: 8, |
| 7 | |
| 8 | // Remove values that don't match any union variant (default: false) |
| 9 | removeUnknownUnionType: false, |
| 10 | }); |
Pass one or more functions to transform every string value in the output:
| 1 | const mirror = createMirror(schema, { |
| 2 | sanitize: [(v) => v.trim(), (v) => v.replace(/</g, "<")], |
| 3 | }); |
| 1 | bun test # run tests |
| 2 | bun run bench # run benchmarks |
| 3 | bun run bench:small # benchmark small schemas |
| 4 | bun run bench:compare # compare against z.parse() |
| 5 | bun run typecheck # type check |
| 6 | bun run fix # lint + format |
MIT