# 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](https://joi.dev). You can see a comparation on their [website](https://zod.dev/?id=comparison). 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](https://nodejs.org).
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**.
```typescript
// 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.
```typescript
// 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](https://zod.dev/?id=strings)

## Custom Schema
Match prefers to use custom schema with **TypeScript** rather than **JavaScript**.
```typescript
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.
```typescript
// 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.
```typescript
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.
```typescript
const stringSchema = z.string();
stringSchema.safeParse("fish");
// => { success: true; data: 'fish' }
stringSchema.safeParse(12);
// => { success: false; error: ZodError }
```
## Transform
Transform data after parsing.
```typescript
const stringToNumber = z.string().transform((val) => val.length);
stringToNumber.parse("string"); // => 6
```
## Refine
Customize your validation with the `refine` method from Zod.
```typescript
const myString = z.string().refine((val) => val.length <= 255, {
message: "String can't be more than 255 characters",
});
```
**NOTE**: From the [document](https://zod.dev/?id=refine), 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**
```typescript
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](https://zod.dev/).