<
>
ETHIOCODE
SOFTSELECT
แˆถแแ‰ตแ‹Œแˆญ แˆแˆญแŒซ แˆˆแŠขแ‰ตแ‹ฎแŒตแ‹ซ
P3 ยท L02 ยท ZOD VALIDATION ยท LOADING...
PHASE 3 ยท LESSON 02

Zod โ€” 
แ‹จ Data Validation แ‰€แˆ‹แˆ‰ แˆ˜แŠ•แŒˆแ‹ต! ๐Ÿ›ก๏ธ

แ‹จ User inputแŠ•แฃ แŠฅแŠ“ แ‹จ API responseแŠ• แ‰…แˆญแ… แŠ แˆจแŒ‹แŒแŒก (Validate แŠ แ‹ตแˆญแŒ‰)! แˆตแˆ…แ‰ฐแ‰ตแŠ• แ‰€แ‹ตแˆ›แ‰ฝแˆ แ‹ซแ‹™ โ€” Production แˆ‹แ‹ญ Bug แŠฅแŠ•แ‹ณแ‹ญแˆแŒ แˆญ!
Zod catches bad data before it breaks your app โ€” TypeScript-first schema validation.

แ‹ซแ‹˜แŒ‹แŒ€แ‹: @AppMinds_ET
01Zod แˆแŠ•แ‹ตแŠ• แАแ‹?

Zod โ€” แ‰  TypeScript-first แˆ˜แˆญแˆ… แ‹จแˆšแˆฐแˆซ แ‹จ schema แˆ›แˆจแŒ‹แŒˆแŒซ (validation) library แАแ‹! แ‹จแŒˆแ‰ฃแ‹ แ‹ณแ‰ณ แ‰ตแŠญแŠญแˆˆแŠ› แ‰…แˆญแ… แŠ แˆˆแ‹ แ‹ˆแ‹ญ? แˆˆแˆšแˆˆแ‹แฃ แŠ แ•แˆŠแŠฌแˆฝแŠ‘ แ‰ฝแŒแˆญ แ‹แˆตแŒฅ แŠจแˆ˜แŒแ‰ฃแ‰ฑ แ‰ แŠแ‰ต แ‰€แ‹ตแˆ˜แŠ• แˆ›แˆจแŒ‹แŒˆแŒฅ แŠฅแŠ•แ‰ฝแˆ‹แˆˆแŠ•!
Define schema once โ€” validates data AND generates TypeScript types automatically.

๐Ÿ’ก

npm install zod  ยท  import { z } from 'zod'
Form dataแฃ API responseแฃ env vars โ€” แŠ แŒ แ‰ƒแˆ‹แ‹ญ แ‹ณแ‰ณแŠ• แ‰  Zod แˆ›แˆจแŒ‹แŒˆแŒฅ (Validate แˆ›แ‹ตแˆจแŒ) แŠฅแŠ•แ‰ฝแˆ‹แˆˆแŠ•!
Works with React Hook Form, tRPC, Next.js, and any TypeScript project.

zod-intro.ts
import { z } from 'zod';

// 1. แ‰ แˆ˜แŒ€แˆ˜แˆชแ‹ซ Schema (แ‹จแ‹ณแ‰ณแ‹แŠ• แ‰…แˆญแ…) แแŒ แˆฉ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
const UserSchema = z.object({
  name:  z.string().min(2),
  email: z.string().email(),
  age:   z.number().min(18).max(120),
  role:  z.enum(['admin', 'user']),
});

// 2. แ‹จ TypeScript type แˆซแˆฑ (Auto) แ‹ญแˆแŒ แˆซแˆ! โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
type User = z.infer<typeof UserSchema>;

// 3. Validate โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
const result = UserSchema.safeParse(inputData);
if (result.success) {
  console.log('โœ… Valid!', result.data);
} else {
  console.log('โŒ Errors:', result.error.format());
}
02Zod Types โ€” แˆแˆ‰แˆ แ‹จ Data แŠ แ‹ญแАแ‰ถแ‰ฝ
zod-types.ts
// แˆ˜แˆ แˆจแ‰ณแ‹Š แŠ แ‹ญแАแ‰ถแ‰ฝ (Primitives) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
z.string()  z.number()  z.boolean()  z.date()

// แˆˆ String แ‹จแ‰ฐแ‹˜แŒ‹แŒ แˆ…แŒแŒ‹แ‰ต (Rules) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
z.string().min(2).max(50)   // แ‹จแŠแ‹ฐแˆ แˆญแ‹แˆ˜แ‰ต (Length)
z.string().email()          // แ‰ตแŠญแŠญแˆˆแŠ› email แŠ แ‹ตแˆซแˆป (Valid email)
z.string().url()            // แ‹จ website แŠ แ‹ตแˆซแˆป (URL)
z.string().uuid()           // UUID แŽแˆญแˆ›แ‰ต
z.string().regex(/^\d{4}$/) // แ‰ แŠฅแˆซแˆณแ‰ฝแŠ• แ“แ‰ฐแˆญแŠ• แˆฒแˆฐแˆซ

// แˆˆ Number แ‹จแ‰ฐแ‹˜แŒ‹แŒ แˆ…แŒแŒ‹แ‰ต โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
z.number().min(0).max(100)  // แŠจ แŠฅแˆตแŠจ (Range)
z.number().int()             // แˆ™แˆ‰ แŠ แˆƒแ‹ (integers only)
z.number().positive()        // แŠจแ‹œแˆฎ แ‰ แˆ‹แ‹ญ (Positive numbers)

// แˆŒแˆŽแ‰ฝ แ‹จแ‹ณแ‰ณ แˆตแ‰ฅแˆตแ‰ฆแ‰ฝ (Collections) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
z.array(z.string())         // แˆˆ Array (string[])
z.enum(['a','b','c'])       // แŠจแ‰ฐแ‹ˆแˆฐแŠ‘ แˆแˆญแŒซแ‹Žแ‰ฝ แ‰ฅแ‰ป แˆ˜แˆ†แŠ• แˆฒแŠ–แˆญแ‰ แ‰ต
z.optional(z.string())     // แ‰ขแ‰€แˆญแˆ แ‰ฃแ‹ญแ‰€แˆญแˆ (Optional) แˆฒแˆ†แŠ•
z.nullable(z.string())     // null แˆŠแˆ†แŠ• แ‹จแˆšแ‰ฝแˆ แŠจแˆ†แА
03๐Ÿ”ง Schema Builder โ€” แ‹จแˆซแˆณแ‰ฝแˆแŠ• (Schema) แแŒ แˆฉ!
Interactive Schema Builder
แ‹จ Type แŠ แ‹ญแАแ‰ฑแŠ• แˆแˆจแŒก โ†’ แˆ…แŒแŒ‹แ‰ต แˆตแŒก (OPTIONS) โ†’ แŠจแˆตแˆญ แŒ€แАแˆฌแ‰ต (GENERATE) แ‹ซแ‹ฐแˆญแŒ‹แˆ โ†“
แ‹จFIELD แŠ แ‹ญแАแ‰ถแ‰ฝ แˆแˆจแŒก
๐Ÿ“string
๐Ÿ”ขnumber
โœ…boolean
๐Ÿ“งemail
๐ŸŒurl
๐Ÿ“‹enum
๐Ÿ“ฆarray
๐Ÿ“…date

แ‰ฐแŒจแˆ›แˆช แŠ แˆ›แˆซแŒฎแ‰ฝ (OPTIONS)

แ‹ซแˆ˜แАแŒจแ‹ แ‹จ ZOD แŠฎแ‹ต

04๐ŸŽฎ Live Validator โ€” แŠ แˆแŠ‘แŠ‘ แˆžแŠญแˆฉแ‰ต!
Zod Playground (แˆ˜แˆžแŠจแˆชแ‹ซ)
LIVE โœ…
๐Ÿ–Š๏ธ แ‹จแŽแˆญแˆ แŠ แˆจแŒ‹แŒ‹แŒญ (Form)
๐Ÿ“„ แ‹จJSON แŠ แˆจแŒ‹แŒ‹แŒญ
โšก แ‰…แ…แ‰ แ‰ณแ‹Š แŠ แˆจแŒ‹แŒ‹แŒญ (Real-Time)

แ‹จ User registration แŽแˆญแˆ แˆฒแˆžแˆ‹ แ‹จแˆšแŒˆแ‰ฃแ‹แŠ• JSON Data แ‰…แˆญแ แ‰ตแŠญแŠญแˆ แˆ˜แˆ†แŠ‘แŠ• แŠฅแŠ•แˆ˜แˆญแˆแˆญ (Validate แŠฅแŠ“แ‹ตแˆญแŒ)แข
Edit the JSON and hit Validate โ€” see exactly what Zod catches.

แ‹จแˆšแˆžแˆ‹ แ‹ณแ‰ณ / INPUT DATA (JSON)
แ‹แŒคแ‰ต (RESULT)
แŠจแˆ‹แ‹ญ Validate แ‰แˆแ แˆฒแŒซแŠ‘ แ‹แŒคแ‰ฑ (Result) แŠฅแ‹šแˆ… แŒ‹แˆญ แ‹ญแ‹ˆแŒฃแˆแข

แŠจแˆ‹แ‹ญ แŠจแ‰ฐแ‹˜แˆจแ‹˜แˆฉแ‰ต แˆแˆณแˆŒแ‹Žแ‰ฝ (Preset) แˆแˆจแŒก โ†’ แ‹ˆแ‹ญแˆ แ‹ฐแŒแˆž แ‹จแˆซแˆณแ‰ฝแˆแŠ• แƒแ‰แŠ“ โ†’ Validate แ‰ แˆ‰แ‰ต!
Choose a preset schema and data, or write your own!

แˆ…แŒ‰ (SCHEMA)
แ‹จแŒˆแ‰ฃแ‹ แ‹ณแ‰ณ (DATA)
แ‹จแ‰ฐแŒˆแŠ˜แ‹ แ‹แŒคแ‰ต (RESULT)
Validate แˆฒแ‹ซแ‹ฐแˆญแŒ‰แ‰ต แ‹แŒคแ‰ฑ แŠฅแ‹šแˆ… แ‹ญแ‰ณแ‹ซแˆ...

แŠฅแ‹จแƒแ‹แ‰ฝแˆ แ‰ฃแˆˆแ‰ แ‰ต แ‰…แ…แ‰ แ‰ต แ‹จแˆšแˆฐแˆซ (Real-time) validation โœจ โ€” แŽแˆญแˆ™แŠ• แˆžแˆแ‰ณแ‰ฝแˆ แˆณแ‰ตแŒจแˆญแˆฑ แˆตแˆ…แ‰ฐแ‰ต แŠซแˆˆ แ‹ซแˆณแ‹ซแ‰ฝแŠ‹แˆ!
Real-time validation โ€” each field validates as you type!

๐Ÿ“ แˆ™แˆ‰ แˆตแˆ z.string().min(2)
๐Ÿ“ง แŠขแˆœแ‹ญแˆ (Email) z.string().email()
๐Ÿ”ข แ‹•แ‹ตแˆœ z.number().min(18).max(120)
๐ŸŒ แ‹Œแ‰ฅแˆณแ‹ญแ‰ต z.string().url().optional()
แ‹จแŒแˆแŒˆแˆ› แ‹แŒคแ‰ต (STATUS)
แˆแˆ‰แŠ•แˆ Fields แ‹ซแˆˆแˆแŠ•แˆ แˆตแˆ…แ‰ฐแ‰ต แˆฒแˆžแˆ‰ Submit แˆ›แ‹ตแˆจแŒ แ‹ญแ‰ฝแˆ‹แˆ‰! (แ‹ˆแ‹ญแˆ แˆแˆ‰แˆ แŠ แˆจแŠ•แŒ“แ‹ด แˆฒแˆ†แŠ‘)!
05แ‹จแŒˆแˆƒแ‹ฑ แ‹“แˆˆแˆ โ€” Real World / Production แˆแˆณแˆŒแ‹Žแ‰ฝ
real-world.ts
// โ”€โ”€ แŽแˆญแˆ แˆฒแˆžแˆ‹ + React Hook Form แˆฒแ‰ณแŠจแˆแ‰ แ‰ต โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
const LoginSchema = z.object({
  email:    z.string().email('แ‰ตแŠญแŠญแˆˆแŠ› แŠขแˆœแ‹ญแˆ แ‹ซแˆตแˆแˆแŒ‹แˆ!'),
  password: z.string().min(8, 'แ‰ขแ‹ซแŠ•แˆต 8 แ‹จแŠแ‹ฐแˆ แˆญแ‹แˆ˜แ‰ต (character) แ‹ซแˆตแˆแˆแŒˆแ‹‹แˆ'),
});
const { register } = useForm({ resolver: zodResolver(LoginSchema) });

// โ”€โ”€ แ‹จ API Response แˆ›แˆจแŒ‹แŒˆแŒฅ แˆฒแˆแˆˆแŒ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
const ProductSchema = z.object({
  id: z.number(), name: z.string(),
  price: z.number().positive(),
  tags: z.array(z.string()),
});
const res = await axios.get('/api/product');
const product = ProductSchema.parse(res.data); // โœ… แˆ˜แŒฃแŒฃแˆ แˆ˜แ‰ปแˆ‰ แ‰ณแ‹ญแ‰ทแˆ

// โ”€โ”€ แ‹จ Environment Variables แˆ˜แˆจแŒ‹แŒˆแŒฅ (Environment variables) โ”€โ”€
const EnvSchema = z.object({
  DATABASE_URL: z.string().url(),
  NODE_ENV: z.enum(['development','production']),
});
const env = EnvSchema.parse(process.env);
06๐Ÿ“Œ แ‹‹แŠ“ แ‹‹แŠ“ แАแŒฅแ‰ฆแ‰ฝ แˆ›แˆตแ‰ณแ‹ˆแˆป
1
๐Ÿ›ก๏ธ Schema แ‰ แˆ˜แŒ€แˆ˜แˆชแ‹ซ แ‹ฐแˆจแŒƒ แˆ˜แˆฐแˆซแ‰ฑ

z.object() แ‰ แˆ˜แŒ แ‰€แˆ โ€” แ‹ณแ‰ณ แ‹จแˆšแŠ–แˆจแ‹แŠ• แ‹จแ‰…แ… (Shape) แ‰€แ‹ตแˆ›แ‰ฝแˆ แˆ…แŒ แแŒ แˆฉ! แŠจแ‹šแ‹ซ แ‰ แŠแ‰ตแˆ แˆ›แŒฅแ‹แ‰ต แ‹จแАแ‰ แˆจแ‰ฃแ‰ฝแˆแŠ•แˆ (Bugs) แˆ˜แŠจแˆ‹แŠจแ‹ซ แАแ‹แข Define schema once โ†’ validate everywhere.

2
โœ… safeParse vs parse แ‹ซแˆˆแ‹ แˆแ‹ญแАแ‰ต

safeParse() = แ‰ แ€แŒฅแ‰ณ แˆตแˆ…แ‰ฐแ‰ฑแŠ• แ‹ซแˆตแ‰€แˆซแˆ แŠฅแŠ•แŒ‚ แˆ˜แ‰ฐแŒแ‰ แˆชแ‹ซแ‹แŠ• แŠ แ‹ซแ‰†แˆแˆ (Error throw แŠ แ‹ซแ‹ฐแˆญแŒแˆ) ยท parse() = Zod error throw แŠฅแŠ•แ‹ฒแ‹ซแ‹ฐแˆญแŒ (แ‹ซแˆˆแˆญแˆ…แˆซแˆ„ แˆตแˆ…แ‰ฐแ‰ต แŠฅแŠ•แ‹ฒแ‹ˆแˆจแ‹แˆญ) แ‹ซแ‹ฐแˆญแŒˆแ‹‹แˆแข Use safeParse() for user input always.

3
๐Ÿ”ค แŠฅแˆซแˆฑ แŠ แ‹แ‰† แ‹จแˆšแˆฐแˆซแ‹ Type แˆ˜แŠ–แˆฉ

z.infer<typeof Schema> โ€” TypeScript type แ‹ณแŒแˆ แˆ˜แƒแ แˆณแ‹ซแˆตแˆแˆแŒ แˆซแˆฑแŠ• แ‰ฝแˆŽ (auto-generated) แ‹ญแˆแŒ แˆซแˆ! One source of truth for both runtime and compile-time.

4
๐Ÿ”— แ‰ แˆ›แˆตแ‰ฐแˆณแˆฐแˆญ (Chain) แˆ›แ‹ตแˆจแŒ แ‹จแˆšแŒˆแŠ แŒฅแŠ•แŠซแˆฌ

z.string().email().min(5).max(100) โ€” method-แ‹Žแ‰ฝแŠ• แ‰ แˆ›แ‹ซแ‹ซแ‹ (Chain แ‰ แˆ›แ‹ตแˆจแŒ) แ‰ แ‰€แˆ‹แˆ‰ Validation แˆ…แŒแŒ‹แ‰ตแŠ• แˆ›แˆตแ‰€แˆ˜แŒฅ แ‹ญแ‰ปแˆ‹แˆแข Chain validations fluently and readably.

5
โšก แˆˆแŽแˆญแˆ แˆแ‹ฉ แ‹จแˆ†แА (React Hook Form แŒ‹แˆญ แˆ˜แŒ แ‰€แˆšแ‹ซ)

แ‹จแ‰ฐแŒˆแАแ‰ฃ แ‹จZod Schema แŠจ "zodResolver" แŒ‹ แ‰ แˆแŒแ‰ฃแ‰ฃแ‰ต (perfect integration) แˆˆแˆ˜แแŒ แˆญ แАแ‹แข npm install @hookform/resolvers

07๐ŸŽฏ แˆˆแˆ˜แˆˆแˆ›แˆ˜แ‹ต แ‹จแˆšแŒ แ‰…แˆ (Quiz)
โ“ Zod แ‹แˆตแŒฅ safeParse() แŠฅแŠ“ parse() แˆแ‹ฉแАแ‰ฑ แˆแŠ•แ‹ตแŠ• แАแ‹?
What is the key difference between safeParse() and parse() in Zod?
AsafeParse() แ‰ แŒฃแˆ แˆแŒฃแŠ• (faster) แŠ แˆแƒแ€แˆ แ‹ซแˆˆแ‹ แАแ‹
BsafeParse() แˆตแˆ…แ‰ฐแ‰ตแŠ• (error throw) แŠ แ‹ซแ‹ฐแˆญแŒแˆ โ€” ื‘ืžแˆˆแˆต { success, data/error } แ‹จแˆšแˆˆแ‹แŠ• object แˆ†แŠ– แ‹ญแˆฐแŒฃแˆ โœ…
Cparse() แ‹จ TypeScript typesแŠ• แ‹ญแˆแŒฅแˆซแˆ
DแŠ แŠ•แ‹ณแ‰ฝ แˆแ‹ฉแАแ‰ต แŠ แˆ‹แ‰ธแ‹แˆแข แˆแˆˆแ‰ฑแˆ แŠ แŠ•แ‹ต แŠ แ‹ญแАแ‰ต แŠฅแŠ“ แ‰ฐแˆ˜แŒฃแŒฃแŠ แŠ“แ‰ธแ‹