iT邦幫忙

2025 iThome 鐵人賽

DAY 14
0
Modern Web

30 天,讓 TypeScript 把你的 Node.js 開發再升級系列 第 14

Day 14|API 驗證救星:用 Zod 驗證來檢查

  • 分享至 

  • xImage
  •  

在開發後端 API 的時候,你一定遇過這些狀況:

  • 前端傳來的資料少了一個欄位。
  • 輸入的字串太長,直接讓資料庫報錯。
  • 原本應該是 boolean,結果卻收到 "true"1

如果每次都要手動檢查 req.body,程式碼會變得又長又難維護。

👉 這時候,Zod 就是我們的防呆神器


1. 為什麼要用 Zod?

Zod 是一個 TypeScript-first 的資料驗證工具,它的特點包括:

  • 語法直覺z.string().min(1) 就能定義規則。
  • 與 TS 整合:Schema 本身就是型別,可以直接推導。
  • 後端防呆:避免錯誤資料寫進資料庫。

2. Zod 基礎知識

先來看一個小範例:

import { z } from "zod";

// 定義 schema
const userSchema = z.object({
  name: z.string().min(1, "Name is required"),
  age: z.number().int().min(0),
});

// 驗證資料
const result = userSchema.safeParse({ name: "", age: -1 });

if (!result.success) {
  console.log(result.error.errors);
  // [
  //   { message: "Name is required", path: ["name"] },
  //   { message: "Number must be greater than or equal to 0", path: ["age"] }
  // ]
}

常見型別:

  • z.string():字串
  • z.number():數字
  • z.boolean():布林
  • z.object({...}):物件

常用驗證方法:

  • .min(n) / .max(n):限制範圍
  • .optional():欄位可選
  • .email():檢查 Email 格式

也可用線上 Zod Playground 快速測試一下:

https://zod-playground.vercel.app/?appdata=N4IgzgxgFgpgtgQxALhALwHQHsBGArGCAFwApgAdAOwAJrKE4ZlrMwiAnAS0oHMSBKDHG4kAjABpq5EADkGMapzDV2MAI4BXTqoAm0-uKq0EPJiwyUNcHDHYCM3UoOGUSABgNUAvvwDcIcRAANwQAGw0YMBQAbRBgOnlmaQApLChKaUkTMwAmN2ovEABdQKDbME4sShQQABYMUQbRAJAlAC0sHQBZbk4UADMwsBgvIA


3. 安裝 Zod

在專案根目錄執行:

npm install zod

4. 建立驗證 Schema

建立 src/validator/todoValidation.ts

import { z } from "zod";

export const createTodoSchema = z.object({
  title: z
    .string()
    .min(1, { message: "Title is required" })
    .max(100, { message: "Title must be at most 100 characters" }),
});

export const updateTodoSchema = z.object({
  title: z.string().optional(),
  completed: z.boolean().optional(),
});

5. 在 Controller 使用驗證

todoController.ts 中對 createTodoupdateTodo 套用 .safeParse()

import { Request, Response, NextFunction } from "express";
import { AppDataSource } from "../config/db";
import { Todo } from "../entities/Todo";
import { createTodoSchema, updateTodoSchema } from "../validator/todoValidation";

const todoRepository = AppDataSource.getRepository(Todo);

export async function createTodo(req: Request, res: Response, next: NextFunction) {
  try {
    const parsed = createTodoSchema.safeParse(req.body);
    if (!parsed.success) {
      res.status(400).json({ status: "failed", message: "標題過長或過短" });
      return;
    }

    const newTodo = todoRepository.create({ title: parsed.data.title });
    const savedTodo = await todoRepository.save(newTodo);
    res.status(201).json({ status: "success", data: savedTodo });
  } catch (error) {
    next(error);
  }
}

export async function updateTodo(req: Request, res: Response, next: NextFunction) {
  try {
    const { id } = req.params;
    const parsed = updateTodoSchema.safeParse(req.body);

    if (!parsed.success) {
      res.status(400).json({ status: "failed", message: "更新資料格式錯誤" });
      return;
    }

    const todo = await todoRepository.findOneBy({ id });
    if (!todo) {
      res.status(404).json({ status: "error", message: "Todo not found" });
      return;
    }

    todo.title = parsed.data.title ?? todo.title;
    todo.completed = parsed.data.completed ?? todo.completed;

    const updatedTodo = await todoRepository.save(todo);
    res.json({ status: "success", data: updatedTodo });
  } catch (error) {
    next(error);
  }
}

6. 成果展示

  • ✅ 正確資料 → 正常新增 / 更新

  • ❌ 錯誤資料 → 直接被擋下並回傳錯誤訊息


7. 總結

今天我們學到:

  • Zod 是一個簡單直覺的 驗證工具
  • 透過 safeParse() 可以有效攔截不合法資料。
  • 在 API Controller 直接使用 Schema,就能大幅提升專案的安全性與可維護性。

下次寫 API 時,別忘了這個小幫手!


補充資源

commit : add zod validation

Github 連結


上一篇
Day 13|一致的程式碼:ESLint 導入
下一篇
Day 15|API 安全升級:JWT 登入驗證全流程實作
系列文
30 天,讓 TypeScript 把你的 Node.js 開發再升級19
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言