tutorbook icon indicating copy to clipboard operation
tutorbook copied to clipboard

Migrate type validators to `zod`

Open nicholaschiang opened this issue 4 years ago • 3 comments
trafficstars

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).

nicholaschiang avatar May 18 '21 22:05 nicholaschiang

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.

nicholaschiang avatar May 18 '21 22:05 nicholaschiang

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.

nicholaschiang avatar May 24 '21 23:05 nicholaschiang

I'd love to take this issue! Is there anything else I should be aware of before working on this?

jasonappah avatar Oct 13 '21 15:10 jasonappah