Union Types และ Literal Types
Union Types และ Literal Types
Section titled “Union Types และ Literal Types”Union Types ช่วยให้ตัวแปรรับได้หลาย type ส่วน Literal Types จำกัดค่าที่เป็นไปได้ — สองเครื่องมือนี้ทำให้ TypeScript ทรงพลังมาก
Union Types
Section titled “Union Types”// ตัวแปรที่รับได้หลาย typelet id: string | number;id = "ABC-001"; // OKid = 42; // OK// id = true; // Error!
// Union ใน function parameterfunction formatId(id: string | number): string { if (typeof id === "string") { return id.toUpperCase(); } return `#${id}`;}// JS ไม่มี union type — ต้อง check เองfunction formatId(id) { if (typeof id === "string") return id.toUpperCase(); return `#${id}`;}from typing import Uniondef format_id(id: Union[str, int]) -> str: if isinstance(id, str): return id.upper() return f"#{id}"-- SQL ไม่มี union type โดยตรง ใช้ CASE แทนSELECT CASE WHEN id_type = 'string' THEN UPPER(id_value) ELSE CONCAT('#', id_value)END AS formatted_id FROM records;Literal Types
Section titled “Literal Types”// String literal types — จำกัดค่าที่เป็นไปได้type Role = "admin" | "editor" | "viewer";type Theme = "light" | "dark" | "system";
let userRole: Role = "admin"; // OK// userRole = "superadmin"; // Error! ไม่อยู่ใน union
// Numeric literal typestype DiceRoll = 1 | 2 | 3 | 4 | 5 | 6;let roll: DiceRoll = 3; // OK
// Boolean literal — ใช้น้อยแต่มีประโยชน์type True = true;Type Narrowing
Section titled “Type Narrowing”TypeScript สามารถ narrow type ลงได้เมื่อเรา check condition:
function processValue(value: string | number | boolean): string { // typeof guard if (typeof value === "string") { return value.toUpperCase(); // TS รู้ว่าเป็น string } if (typeof value === "number") { return value.toFixed(2); // TS รู้ว่าเป็น number } return value ? "yes" : "no"; // TS รู้ว่าเป็น boolean}
// Truthiness narrowingfunction printName(name: string | null): void { if (name) { console.log(name.toUpperCase()); // TS รู้ว่าไม่ใช่ null }}Discriminated Unions
Section titled “Discriminated Unions”Pattern ที่ทรงพลังที่สุดของ TypeScript — ใช้ common field เป็นตัวแยก type:
interface LoadingState { status: "loading";}
interface SuccessState { status: "success"; data: string[];}
interface ErrorState { status: "error"; message: string;}
type RequestState = LoadingState | SuccessState | ErrorState;
function renderUI(state: RequestState): string { switch (state.status) { case "loading": return "กำลังโหลด..."; case "success": return `พบข้อมูล ${state.data.length} รายการ`; // TS รู้ว่ามี data case "error": return `เกิดข้อผิดพลาด: ${state.message}`; // TS รู้ว่ามี message }}Exhaustive Check ด้วย never
Section titled “Exhaustive Check ด้วย never”function assertNever(value: never): never { throw new Error(`Unexpected value: ${value}`);}
function handleState(state: RequestState): string { switch (state.status) { case "loading": return "loading..."; case "success": return "done"; case "error": return "failed"; default: return assertNever(state); // ถ้าเพิ่ม status ใหม่แล้วลืม handle — TS จะ error ตรงนี้ }}