Try   HackMD

Validation with zod

Validation your data before it get in to your code is the clean way.

  • Know actually, what kind of data you gonna get
  • No some kind of unknown bug when in production

Why do we need to validate our data?

Data that came after validation will be more accurate than the normal data. Data can be manipulated in any way, so validation before any action is a secure choice.

Why do we use zod?

There are some alternatives to Zod to validate your data with joi. You can see a comparation on their website. We will use Zod for now. Zod can be used with JavaScript and TypeScript. You can parse the data without doing any validation.

Installation

In this example, we will use Zod in the NodeJS project. We will need NodeJS.
After installing the NodeJS, you can create a node project with the command npm init -y in your project folder. The node will generate the project for you.

Install zod dependency

To install Zod dependency, you can run this command: npm install zod.

Schema

Zod will need Zod schema to define the data from you.
The Zod schema will be required by default.

// String schema
const stringSchema = z.string(); 

// Optional
const opStringSchema = z.string().optional();
// or
const opStringSchema = stringSchema().optional();

// Object
const student = z.object({
    name: z.string(),
    age: z.number(),
})

We can do more with pre-build validation like Email, URL, etc.

// Email
const emailSchema = z.string().email();

// URL 
const urlSchema = z.string().url();

// RegEx
const regExSchema = z
    .string()
    .regex(/^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/);

// 

And there are more than this in their docs

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Custom Schema

Match prefers to use custom schema with TypeScript rather than JavaScript.

const px = z.custom<`${number}px`>((val) => {
  return /^\d+px$/.test(val as string);
});

type px = z.infer<typeof px>; // `${number}px`

px.parse("42px"); // "42px"
px.parse("42vw"); // throws;

Custom Error

You can create custom errors too.

// String
const name = z.string({
  required_error: "Name is required",
  invalid_type_error: "Name must be a string",
});

// Number
z.number().lte(5, { message: "this is too big" }); // lte = less than equal to (<=)

Validation

There are 2 preferred ways to validate data with schema:

Parse

Parse will throw the error if the condition is not satisfied.

const stringSchema = z.string();

stringSchema.parse("fish"); // => returns "fish"
stringSchema.parse(12); // throws error

SafeParse

SafeParse method will return an object with success and data or error.

const stringSchema = z.string();

stringSchema.safeParse("fish");
// => { success: true; data: 'fish' }

stringSchema.safeParse(12);
// => { success: false; error: ZodError }

Transform

Transform data after parsing.

const stringToNumber = z.string().transform((val) => val.length);

stringToNumber.parse("string"); // => 6

Refine

Customize your validation with the refine method from Zod.

const myString = z.string().refine((val) => val.length <= 255, {
  message: "String can't be more than 255 characters",
});

NOTE: From the document, Zod said:

⚠ Refinement functions should not throw. Instead they should return a falsy value to signal failure.

Asynchronous

Zod also provides you with async functions.

An Example

const stringSchema = z.string().refine(async (val) => val.length <= 8);

await stringSchema.parseAsync("hello"); // => returns "hello"
await stringSchema.parseAsync("hello world"); // => throws error

Bonus

This is just the surface of the Zod library. If you want more information, you can check out their docs.