以下是我有時會忘記,但實際上簡單且實用的小技巧。
可以重複定義相同的函數,根據不同的參數組合執行不同的邏輯,並保持型別安全。
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
能讓物件或陣列的型別鎖定為常數,讓 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
,因此 name
和 age
的型別會被鎖定為 "John"
和 30
,而不再是 string
和 number
。
直接看範例:
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 的部分先介紹到這裡。接下來介紹另一個常與 TypeScript 搭配使用的工具 Zod。
Zod 是一個資料模式宣告和驗證函式庫。可以用簡潔的語法定義資料結構,並在執行時驗證資料是否符合該結構。
雖然 TypeScript 可以幫助我們在編譯階段檢查型別,但當程式編譯成 JavaScript 後,在執行階段還是有可能因為外部資料不符合預期而出錯。
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" }}
通常用來確保資料是符合預期的,以下是幾個常見的範例:
實際使用案例會在下一篇會分享。
參考資料:
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/