tutorbook
tutorbook copied to clipboard
Migrate type validators to `zod`
Instead of declaring a type and then declaring the JSON validator for that type separately, I should use a library like zod to only do it once (and then have a single source of truth instead of duplicating code and creating more possibilities for bugs).
See the validators in lib/model, for example, in lib/model/user.ts:
export interface UserInterface extends AccountInterface {
age?: number;
orgs: string[];
zooms: ZoomUser[];
availability: Availability;
mentoring: Subjects;
tutoring: Subjects;
langs: string[];
parents: string[];
verifications: Verification[];
visible: boolean;
featured: Aspect[];
roles: Role[];
tags: UserTag[];
reference: string;
timezone: string;
token?: string;
hash?: string;
}
export function isUserJSON(json: unknown): json is UserJSON {
if (!isAccountJSON(json)) return false;
if (!isJSON(json)) return false;
if (json.age && typeof json.age !== 'number') return false;
if (!isStringArray(json.orgs)) return false;
if (!isArray(json.zooms, isZoomUserJSON)) return false;
if (!isAvailabilityJSON(json.availability)) return false;
if (!isSubjects(json.mentoring)) return false;
if (!isSubjects(json.tutoring)) return false;
if (!isStringArray(json.langs)) return false;
if (!isStringArray(json.parents)) return false;
if (!isArray(json.verifications, isVerificationJSON)) return false;
if (typeof json.visible !== 'boolean') return false;
if (!isArray(json.featured, isAspect)) return false;
if (!isArray(json.roles, isRole)) return false;
if (!isArray(json.tags, isUserTag)) return false;
if (typeof json.reference !== 'string') return false;
if (typeof json.timezone !== 'string') return false;
if (json.token && typeof json.token !== 'string') return false;
if (json.hash && typeof json.hash !== 'string') return false;
return true;
}
All of that ☝️ could have been written once using a zod type validator.
Also, zod is nicer because it throws the specific validation error instead of simply returning false (like the above validator function). That way, the client knows exactly why it got a 400 - Invalid Request Body API error and how to fix it.
I'd love to take this issue! Is there anything else I should be aware of before working on this?