Skip to content

Union Types และ Literal Types

Union Types ช่วยให้ตัวแปรรับได้หลาย type ส่วน Literal Types จำกัดค่าที่เป็นไปได้ — สองเครื่องมือนี้ทำให้ TypeScript ทรงพลังมาก

// ตัวแปรที่รับได้หลาย type
let id: string | number;
id = "ABC-001"; // OK
id = 42; // OK
// id = true; // Error!
// Union ใน function parameter
function formatId(id: string | number): string {
if (typeof id === "string") {
return id.toUpperCase();
}
return `#${id}`;
}
// String literal types — จำกัดค่าที่เป็นไปได้
type Role = "admin" | "editor" | "viewer";
type Theme = "light" | "dark" | "system";
let userRole: Role = "admin"; // OK
// userRole = "superadmin"; // Error! ไม่อยู่ใน union
// Numeric literal types
type DiceRoll = 1 | 2 | 3 | 4 | 5 | 6;
let roll: DiceRoll = 3; // OK
// Boolean literal — ใช้น้อยแต่มีประโยชน์
type True = true;

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 narrowing
function printName(name: string | null): void {
if (name) {
console.log(name.toUpperCase()); // TS รู้ว่าไม่ใช่ null
}
}

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
}
}
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 ตรงนี้
}
}