Extending Zod #2616
Unanswered
angelhdzdev
asked this question in
Q&A
Extending Zod
#2616
Replies: 3 comments
-
UpdateI think I'm very close... or not? declare module 'zod' {
type ZodPassword = {
min(num: number): z.ZodPassword
atLeastOne(kind: 'digit' | 'symbol' | 'uppercase'): z.ZodPassword & ReturnType<z.ZodString['refine']>
nonempty(): z.ZodPassword
}
let password: () => ZodPassword
}
z.password = function (): z.ZodPassword {
let result: any
let validation: any = z.string()
const obj: z.ZodPassword = {
nonempty() {
validation = validation.nonempty()
return obj
},
min(num: number) {
validation = validation.min(num)
return obj
},
atLeastOne(kind: 'digit' | 'symbol' | 'uppercase') {
let data: {message: string, regex: RegExp} = {regex: null, message: `At least one ${kind} expected`}
if (kind === 'uppercase') {
data.regex = /^(?=.*[A-Z]).+$/g
}
if (kind === 'digit') {
data.regex = /^(?=.*[0-9]).+$/g
}
if (kind === 'symbol') {
data.regex = /^(?=.*[^a-zA-Z0-9]).+$/g
}
let who
if (!result) {
who = validation
} else {
who = result
}
result = who.refine(
(v) => {
return data.regex.test(v)
},
{ message: data.message }
)
return {
...obj,
...result
}
}
}
return obj
} |
Beta Was this translation helpful? Give feedback.
0 replies
-
Update 2I think I did it!!!??? But I would prefer not having to call the declare module 'zod' {
type ZodPassword = {
min(num: number): z.ZodPassword
atLeastOne(kind: 'digit' | 'symbol' | 'uppercase'): z.ZodPassword
nonempty(): z.ZodPassword
resolve(): z.ZodString
}
let password: () => ZodPassword
}
z.password = function (): z.ZodPassword {
let validation: z.ZodString = z.string()
const obj: z.ZodPassword = {
resolve() {
return validation
},
nonempty() {
validation = validation.nonempty()
return obj
},
min(num: number) {
validation = validation.min(num)
return obj
},
atLeastOne(kind: 'digit' | 'symbol' | 'uppercase') {
let data: { message: string; regex: RegExp } = {
regex: null,
message: `At least one ${kind} expected`,
}
if (kind === 'uppercase') {
data.regex = /^(?=.*[A-Z]).+$/g
}
if (kind === 'digit') {
data.regex = /^(?=.*[0-9]).+$/g
}
if (kind === 'symbol') {
data.regex = /^(?=.*[^a-zA-Z0-9]).+$/g
}
validation = validation.regex(data.regex, data.message)
return {
...obj,
}
},
}
return obj
}
const RegisterSchema = z.object({
email: z.string().email().nonempty(),
password: z
.password()
.nonempty()
.min(6)
.atLeastOne('digit')
.atLeastOne('symbol')
.atLeastOne('uppercase')
.resolve()
}) |
Beta Was this translation helpful? Give feedback.
0 replies
-
I just have a file like: import { z as zod } from 'zod';
export const z = {
...zod,
numericId: () => zod.coerce.number().int().safe(),
}; and then import this file across my project. If you need namespace support, if you will have to use something like: /* eslint-disable @typescript-eslint/no-namespace */
// eslint-disable-next-line canonical/no-restricted-imports
import * as zod from 'zod';
export namespace z {
// @ts-expect-error TODO
export * from 'zod';
export const numericId = () => zod.coerce.number().int().safe();
} |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Hi! Loving this library and promoting it. Using it in Nuxt 3, NestJS, everywhere.
This time, I have this:
It works great!
But then I wanted to extend
z
with my own validatorsz.password()
with the methodsmin
andatLeastOne
.I kinda did it, but inside each method, I didn't know what to do, only than returning the object itself to create the chaining.
Tried defining a variable
validations
, and assigning to it in every method, but then what!?Unless each method is supposed to return a complex object, that contains the current validation, and all the methods for the chaining.
Can someone point me in the right direction? 😊💚🔥
Beta Was this translation helpful? Give feedback.
All reactions