import * as vi from "vitest"
import { z } from "zod"
import { zx } from "@traversable/zod"
// Using `zx.deepReadonly.writeable` here to make it easier to visualize `zx.deepReadonly`'s behavior:
vi.expect.soft(zx.deepReadonly.writeable(
z.object({
a: z.number(),
b: z.readonly(z.string()),
c: z.object({
d: z.array(z.object({
e: z.number().max(1),
f: z.boolean()
})).length(10)
})
})
)).toMatchInlineSnapshot
(`
"z.object({
a: z.number().readonly(),
b: z.string().readonly(),
c: z.object({
d: z.array(z.object({
e: z.number().max(1).readonly(),
f: z.boolean().readonly()
})).length(10).readonly()
}).readonly()
})"
`)
zx.deepReadonlyConverts an arbitrary zod schema into its "deeply-readonly" form.
That just means that the schema will be traversed, and wrap all z.object z.object
properties with z.readonly z.readonly.
Any properties that were already readonly will be left as-is, since re-wrapping again doesn't do much besides make the schema's type harder to read.
zx.deepReadonly's behavior is configurable at the typelevel via
the defaults.typelevel options.typelevel property:
defaults.typelevel "semantic" (default): leave the schema untouched, but wrap it
in a no-op interface (deepReadonly.Semantic) to make things explicit
defaults.typelevel "applyToTypesOnly": apply the transformation to the schema's
output type and wrap it in z.ZodType z.ZodType
defaults.typelevel "preserveSchemaType": zx.deepReadonly will
return what it got, type untouched
import * as vi from "vitest"
import { z } from "zod"
import { zx } from "@traversable/zod"
// Using `zx.deepReadonly.writeable` here to make it easier to visualize `zx.deepReadonly`'s behavior:
vi.expect.soft(zx.deepReadonly.writeable(
z.object({
a: z.number(),
b: z.readonly(z.string()),
c: z.object({
d: z.array(z.object({
e: z.number().max(1),
f: z.boolean()
})).length(10)
})
})
)).toMatchInlineSnapshot
(`
"z.object({
a: z.number().readonly(),
b: z.string().readonly(),
c: z.object({
d: z.array(z.object({
e: z.number().max(1).readonly(),
f: z.boolean().readonly()
})).length(10).readonly()
}).readonly()
})"
`)
zx.deepReadonlyConverts an arbitrary zod schema into its "deeply-readonly" form.
That just means that the schema will be traversed, and wrap all z.object z.object
properties with z.readonly z.readonly.
Any properties that were already readonly will be left as-is, since re-wrapping again doesn't do much besides make the schema's type harder to read.
zx.deepReadonly's behavior is configurable at the typelevel via
the defaults.typelevel options.typelevel property:
defaults.typelevel "semantic" (default): leave the schema untouched, but wrap it
in a no-op interface (deepReadonly.Semantic) to make things explicit
defaults.typelevel "applyToTypesOnly": apply the transformation to the schema's
output type and wrap it in z.ZodType z.ZodType
defaults.typelevel "preserveSchemaType": zx.deepReadonly will
return what it got, type untouched
import * as vi from "vitest"
import { z } from "zod"
import { zx } from "@traversable/zod"
// Using `zx.deepReadonly.writeable` here to make it easier to visualize `zx.deepReadonly`'s behavior:
vi.expect.soft(zx.deepReadonly.writeable(
z.object({
a: z.number(),
b: z.readonly(z.string()),
c: z.object({
d: z.array(z.object({
e: z.number().max(1),
f: z.boolean()
})).length(10)
})
})
)).toMatchInlineSnapshot
(`
"z.object({
a: z.number().readonly(),
b: z.string().readonly(),
c: z.object({
d: z.array(z.object({
e: z.number().max(1).readonly(),
f: z.boolean().readonly()
})).length(10).readonly()
}).readonly()
})"
`)
zx.deepReadonlyConverts an arbitrary zod schema into its "deeply-readonly" form.
That just means that the schema will be traversed, and wrap all z.object z.object
properties with z.readonly z.readonly.
Any properties that were already readonly will be left as-is, since re-wrapping again doesn't do much besides make the schema's type harder to read.
zx.deepReadonly's behavior is configurable at the typelevel via
the defaults.typelevel options.typelevel property:
defaults.typelevel "semantic" (default): leave the schema untouched, but wrap it
in a no-op interface (deepReadonly.Semantic) to make things explicit
defaults.typelevel "applyToTypesOnly": apply the transformation to the schema's
output type and wrap it in z.ZodType z.ZodType
defaults.typelevel "preserveSchemaType": zx.deepReadonly will
return what it got, type untouched
import * as vi from "vitest"
import { z } from "zod"
import { zx } from "@traversable/zod"
// Using `zx.deepReadonly.writeable` here to make it easier to visualize `zx.deepReadonly`'s behavior:
vi.expect.soft(zx.deepReadonly.writeable(
z.object({
a: z.number(),
b: z.readonly(z.string()),
c: z.object({
d: z.array(z.object({
e: z.number().max(1),
f: z.boolean()
})).length(10)
})
})
)).toMatchInlineSnapshot
(`
"z.object({
a: z.number().readonly(),
b: z.string().readonly(),
c: z.object({
d: z.array(z.object({
e: z.number().max(1).readonly(),
f: z.boolean().readonly()
})).length(10).readonly()
}).readonly()
})"
`)
zx.deepReadonlyConverts an arbitrary zod schema into its "deeply-readonly" form.
That just means that the schema will be traversed, and wrap all z.object
z.objectproperties with z.readonlyz.readonly.Any properties that were already readonly will be left as-is, since re-wrapping again doesn't do much besides make the schema's type harder to read.
Options
zx.deepReadonly's behavior is configurable at the typelevel via the defaults.typeleveloptions.typelevelproperty:defaults.typelevel
"semantic"(default): leave the schema untouched, but wrap it in a no-op interface (deepReadonly.Semantic) to make things explicitdefaults.typelevel
"applyToTypesOnly": apply the transformation to the schema's output type and wrap it in z.ZodTypez.ZodTypedefaults.typelevel
"preserveSchemaType":zx.deepReadonlywill return what it got, type untouched