iT邦幫忙

2024 iThome 鐵人賽

DAY 6
0
Modern Web

前進React 生態系 : 技術應用與概念解析系列 第 6

Day 06 - TypeScript 語法技巧與 Zod 簡介

  • 分享至 

  • xImage
  •  

其他 TypeScript 語法技巧

以下是我有時會忘記,但實際上簡單且實用的小技巧。

Function Overloads

可以重複定義相同的函數,根據不同的參數組合執行不同的邏輯,並保持型別安全。

function printUserInfo(name: string): void;
function printUserInfo(age: number): void;

function printUserInfo(info: string | number): void {
  if (typeof info === "string") {
    console.log(`Name: ${info}`);
  } else {
    console.log(`Age: ${info}`);
  }
}

printUserInfo("John"); // Name: John
printUserInfo(30); // Age: 30

在這個例子中,printUserInfo 可以根據參數的型別執行不同的邏輯。

as const

as const 能讓物件或陣列的型別鎖定為常數,讓 TypeScript推斷出更精確的型別。

  • 沒有使用 as const 的情況
const roles = ["admin", "editor", "viewer"];
type Role = (typeof roles)[number]; //string
roles.push("user");
  • 使用 as const 的情況
const roles = ["admin", "editor", "viewer"] as const;
type Role = (typeof roles)[number]; // "admin" | "editor" | "viewer"
roles.push("user"); // 這會導致錯誤,因為是 readonly

陣列會變成 readonly 的 tuple

  • 物件屬性使用 as const
const user = {
  name: "John",
  age: 30,
} as const;

type User = typeof user; // { readonly name: "John"; readonly age: 30; }

物件屬性會變成 readonly,因此 nameage 的型別會被鎖定為 "John"30,而不再是 stringnumber

Template Literal Types

直接看範例:

type Name = "John";
type Greeting = `Hello ${Name}`;

也可以搭配 union types 使用

type AllRoles = "admin" | "editor" | "viewer";
type UserRole = `user-${AllRoles}`; // "user-admin" | "user-editor" | "user-viewer"

推薦 TypeScript 相關的 VSCode Extension

  • Pretty TypeScript Errors : 讓 TypeScript 錯誤訊息變得更美觀且易於理解。
  • Prettify TypeScript : 當使用 TypeScript 時,常常無法一眼看清完整的型別內容,使用擴充後型別樣式可以一目了然。
  • JSON to TS : 當資料結構複雜時,手動定義 TypeScript 型別很麻煩。這個擴充功能可以透過貼上 JSON 資料自動生成對應的 TypeScript 型別。
  • Total TypeScript : 由 TotalTypeScript 網站作者開發的,有語法指南和錯誤訊息翻譯,網站上也有許多不錯的 TypeScript 學習資源。

由於未來篇幅關係,TypeScript 的部分先介紹到這裡。接下來介紹另一個常與 TypeScript 搭配使用的工具 Zod。

Zod 是什麼?

Zod 是一個資料模式宣告和驗證函式庫。可以用簡潔的語法定義資料結構,並在執行時驗證資料是否符合該結構。

為什麼需要用到 Zod ?

雖然 TypeScript 可以幫助我們在編譯階段檢查型別,但當程式編譯成 JavaScript 後,在執行階段還是有可能因為外部資料不符合預期而出錯。

定義 Schema

Zod 的語法與 TypeScript 非常相似,只要定義好 schema,就可以同時用在型別驗證和型別推斷。

使用 z.infer 可以從 Zod schema 推斷出靜態型別:

import { z } from "zod";

const userSchema = z.object({
  name: z.string(),
  age: z.number(),
});

type User = z.infer<typeof userSchema>; // { name: string, age: number }

資料驗證

parse : 需要搭配 try-catch 來處理,不然出現錯誤可能會導致畫面無法顯示

const userData = { name: "John", age: 30 };

try {
  const user = UserSchema.parse(userData);
  console.log(user);
  // 驗證成功
  // { name: "John", age: 30 }
} catch (error) {
  console.error(error);
  // ZodError
}

safeParse: 不會拋出錯誤,會回傳一個帶有 success 屬性的結果物件

const result = UserSchema.safeParse(userData);
console.log(result);
// 驗證成功
// { success: true; data: { name: "John", age: 30 }
// 錯誤的情況
// { success: false; error: { "issues": [ ... ], "name": "ZodError" }}

Zod 的使用時機

通常用來確保資料是符合預期的,以下是幾個常見的範例:

  1. 表單驗證:通常會搭配 React Hook Form 等表單工具,確保使用者輸入的資料符合格式。
  2. API 資料驗證:確保從後端或外部 API 接收的資料符合預期的型別與結構。
  3. 外部資料驗證:例如 localStorage 或 URL 參數等。

實際使用案例會在下一篇會分享。

參考資料:
https://www.typescriptlang.org/docs/handbook/2/functions.html#function-overloads
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions
https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html
https://zod.dev/


上一篇
Day 05 - 掌握 ComponentProps:讓 React 元件型別更輕鬆
下一篇
Day 07 - 結合 Zod 與 React Hook Form 實現簡潔的表單管理
系列文
前進React 生態系 : 技術應用與概念解析30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言