Blog>
Snippets

Implementing Custom Validation Logic with TypeScript Types

Provide an example of implementing custom synchronous and asynchronous form validations using TypeScript, leveraging typed validation schemas that align with the form data model.
type FormValues = {
  email: string;
  username: string;
};

const emailValidator = (value: string) => {
  const emailRegex = /^[^@\s]+@[^@\s\.]+\.[^@\.\s]+$/;
  return emailRegex.test(value) ? undefined : 'Invalid email format';
};

const usernameValidator = async (value: string) => {
  const bannedUsernames = await getBannedUsernames(); // Hypothetical async call
  return bannedUsernames.includes(value) ? 'Username is not allowed' : undefined;
};
Defines TypeScript types for form values and includes both synchronous (emailValidator) and asynchronous (usernameValidator) validation functions. The emailValidator uses a regex to validate email format synchronously, while usernameValidator checks against a list of banned usernames asynchronously using a hypothetical API call.
const validateForm = async (values: FormValues) => {
  const errors: Partial<FormValues> = {};
  errors.email = emailValidator(values.email);
  errors.username = await usernameValidator(values.username);

  return errors;
};
Defines an asynchronous function to validate the entire form. It checks each field using the defined validators, awaits any asynchronous validators, and collects the errors into an object that maps to the FormValues type. This function can be used to validate form submissions or to implement real-time validation in user interfaces.