Last active
January 23, 2023 13:35
-
-
Save gsbelarus/2c4647201773f2fe3e4012633a3bb26f to your computer and use it in GitHub Desktop.
Example of Zod usage for the arcticle on dev.to
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// link to the article: | |
// https://dev.to/andreik/zod-validatsiia-i-vyvod-tipov-na-osnovanii-skhiemy-dannykh-4n3l | |
import { z } from "https://deno.land/x/zod/mod.ts"; | |
const Levels = ['J1', 'J2', 'J3', 'M1', 'M2', 'M3', 'S1', 'S2', 'S3'] as const; | |
const Skill = z.object({ | |
id: z.string().uuid(), | |
name: z.string().min(1).max(60) | |
}); | |
const PureEmployee = z.object({ | |
id: z.string().uuid(), | |
name: | |
z.object({ | |
firstName: z.string().regex(/(([A-Z]{1}[a-z]{1,40})(\s[A-Z]{1}[a-z]{1,40})?)/), | |
lastName: z.string().regex(/[A-Z]{1}[a-z]{1,40}/) | |
}) | |
.transform( ({firstName, lastName}) => `${firstName} ${lastName}` ), | |
dob: z.date() | |
.min(new Date('01-01-1950Z')) | |
.min(new Date('31-12-2100Z')) | |
.optional(), | |
employmentDate: z.date() | |
.min(new Date('01-01-2000Z')) | |
.min(new Date('31-12-2100Z')), | |
dismissalDate: z.date() | |
.min(new Date('01-01-2000Z')) | |
.min(new Date('31-12-2100Z')) | |
.optional(), | |
level: z.enum(Levels).optional(), | |
skills: Skill | |
.array() | |
.min(1) | |
.max(100) | |
.refine( s => (new Set(s.map( i => i.name ))).size === s.length, 'Duplicate skills are not allowed!') | |
.optional() | |
}); | |
const Employee = PureEmployee | |
.refine( | |
obj => typeof(obj.dob) === 'undefined' || | |
(obj.employmentDate.getTime() - obj.dob.getTime()) > 16 * 365 * 24 * 60 * 60 * 1000, | |
{ | |
message: 'Too young to work!' | |
} | |
) | |
.refine( | |
obj => typeof(obj.dismissalDate) === 'undefined' || | |
(obj.dismissalDate.getTime() >= obj.employmentDate.getTime()), | |
{ | |
message: 'Dismissal date is before employment!' | |
} | |
); | |
// this will parse successfully | |
const employee = Employee.parse({ | |
id: 'eceffe7a-bbe6-41e9-bdc3-09b2970a0d8c', | |
name: { | |
firstName: 'James', | |
lastName: 'Bond' | |
}, | |
dob : new Date('01-01-1980Z'), | |
employmentDate : new Date('01-01-2010Z'), | |
dismissalDate : new Date('01-01-2011Z'), | |
level: 'J1', | |
skills: [ | |
{ id: 'eceffe7a-bbe6-41e9-bdc3-09b2970a0d8c', name: 'abc' } | |
] | |
}); | |
console.log(employee); | |
// this will parse with errors | |
console.log(Employee.safeParse({ | |
id: 'eceffe7a-bbe6-41e9-bdc3-09b2970a0d8c', | |
name: { | |
firstName: 'James', | |
lastName: 'Bond' | |
}, | |
dob : new Date('01-01-1980Z'), | |
employmentDate : new Date('01-01-2010Z'), | |
dismissalDate : new Date('01-01-2011Z'), | |
level: 'J1', | |
skills: [ | |
{ id: 'eceffe7a-bbe6-41e9-bdc3-09b2970a0d8c', name: 'abc' }, | |
{ id: 'eceffe7a-bbe6-41e9-bdc3-09b2970a0d8c', name: 'abc' } | |
] | |
})); | |
const PM = PureEmployee.extend({ | |
projectName: z.string() | |
}); | |
// will not parse without project name specified | |
console.log(PM.safeParse({ | |
id: 'eceffe7a-bbe6-41e9-bdc3-09b2970a0d8c', | |
name: { | |
firstName: 'James', | |
lastName: 'Bond' | |
}, | |
dob : new Date('01-01-1980Z'), | |
employmentDate : new Date('01-01-2010Z'), | |
dismissalDate : new Date('01-01-2011Z'), | |
level: 'J1', | |
skills: [ | |
{ id: 'eceffe7a-bbe6-41e9-bdc3-09b2970a0d8c', name: 'abc' } | |
] | |
})); | |
type Employee = z.infer<typeof Employee>; | |
type PM = z.infer<typeof PM>; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Link to the article:
https://dev.to/andreik/zod-validatsiia-i-vyvod-tipov-na-osnovanii-skhiemy-dannykh-4n3l