Skip to content

Type System (ระบบ type ข้อมูล)

ระบบ type ข้อมูลของ TypeScript ที่ช่วยตรวจสอบความถูกต้องของโค้ดขณะพัฒนาและลดข้อผิดพลาด

ระบบ Typeคำอธิบายตัวอย่าง
Static Typingตรวจสอบ type ขณะ compile-timelet name: string = "John"
Type Inferenceอนุมาน type โดยอัตโนมัติจากค่าlet name = "John" (อนุมานเป็น string)
Structural Typingตรวจสอบความเข้ากันของ type จากโครงสร้างObject ที่มีโครงสร้างตรงกันสามารถใช้แทนกันได้
Type Guardตรวจสอบ type ขณะ runtimeif (typeof data === "string")
Type Castingแปลง type ของข้อมูล(someValue as string) หรือ <string>someValue
Type Assertionยืนยัน type เมื่อเรารู้ดีกว่า TypeScriptdata as User
Type Checkingตรวจสอบว่าข้อมูลเป็น type ที่ต้องการหรือไม่function isString(value: unknown): value is string

Static Typing (การตรวจสอบ type แบบ static)

ตรวจสอบ type ของตัวแปรขณะ compile-time ไม่ใช่ runtime

ts
// ต้องระบุ type ให้ชัดเจน
let username: string = "john";
let age: number = 30;

// จะเกิด error ถ้าใส่ค่าไม่ตรง type
username = 123; // Error: Type 'number' is not assignable to type 'string'

// ตัวอย่างการใช้งานจริง
function calculateTotalPrice(price: number, quantity: number): number {
  return price * quantity;
}

calculateTotalPrice("100", 5); // Error: Argument of type 'string' is not assignable to parameter of type 'number'

ประโยชน์:

  • จับข้อผิดพลาดตั้งแต่ยังไม่รันโปรแกรม
  • ช่วยให้ IDE แนะนำการใช้งานได้ถูกต้อง
  • ทำให้โค้ดอ่านง่ายขึ้น

Type Inference (การอนุมาน type)

TypeScript สามารถเดา type ได้โดยอัตโนมัติจากค่าที่กำหนด

ts
let message = "Hello"; // อนุมานเป็น string อัตโนมัติ
let count = 10; // อนุมานเป็น number
let isActive = true; // อนุมานเป็น boolean

// ฟังก์ชันก็อนุมาน return type ได้
function add(a: number, b: number) {
  return a + b; // อนุมาน return type เป็น number
}

// ตัวอย่างการใช้งานจริง
const items = ["Apple", "Banana", "Orange"]; // อนุมานเป็น string[]
items.forEach(item => {
  console.log(item.toLowerCase()); // สามารถใช้เมธอดของ string ได้โดยไม่ต้องระบุ type
});

Structural Typing (ระบบ type แบบโครงสร้าง)

ตรวจสอบความเข้ากันได้ของ type จากโครงสร้าง ไม่ใช่จากชื่อ type

ts
interface Product {
  id: number;
  name: string;
  price: number;
}

function displayProductInfo(product: Product) {
  console.log(`${product.name}: $${product.price}`);
}

// ใช้งานได้แม้จะไม่ได้ประกาศว่าเป็น Product แต่มีโครงสร้างตรงกัน
const laptop = {
  id: 1,
  name: "MacBook Pro",
  price: 1999,
  inStock: true,
};
displayProductInfo(laptop); // ทำงานได้เพราะมีโครงสร้างที่ต้องการครบ

// ใช้งานไม่ได้ถ้าโครงสร้างไม่ครบ
const invalidProduct = { id: 2, name: "iPhone" };
displayProductInfo(invalidProduct); // Error: Property 'price' is missing

Type Guard (การป้องกัน type)

เทคนิคตรวจสอบ type ขณะ runtime เพื่อให้ TypeScript รู้ type ที่แท้จริง

ts
// ตัวอย่างการใช้งานจริง: ฟังก์ชันรับข้อมูลจาก API ที่อาจเป็นได้หลาย type
function processApiResponse(data: string | number | null) {
  // typeof guard
  if (typeof data === "string") {
    // ภายใน block นี้ TypeScript รู้ว่า data เป็น string
    return `Received text: ${data.toUpperCase()}`;
  } else if (typeof data === "number") {
    // ภายใน block นี้ TypeScript รู้ว่า data เป็น number
    return `Received number: ${data.toFixed(2)}`;
  } else {
    // ภายใน block นี้ TypeScript รู้ว่า data เป็น null
    return "No data received";
  }
}

// instanceof guard (สำหรับ class)
class HttpError extends Error {
  statusCode: number;
  constructor(message: string, statusCode: number) {
    super(message);
    this.statusCode = statusCode;
  }
}

class ValidationError extends Error {
  fieldErrors: Record<string, string>;
  constructor(message: string, fieldErrors: Record<string, string>) {
    super(message);
    this.fieldErrors = fieldErrors;
  }
}

function handleError(error: Error | HttpError | ValidationError) {
  if (error instanceof HttpError) {
    console.error(`HTTP Error ${error.statusCode}: ${error.message}`);
  } else if (error instanceof ValidationError) {
    console.error(`Validation Error: ${error.message}`);
    console.error("Field errors:", error.fieldErrors);
  } else {
    console.error(`Generic Error: ${error.message}`);
  }
}

Type Checking (การตรวจสอบ type)

การตรวจสอบ type ช่วยให้ TypeScript ระบุประเภทข้อมูลได้อย่างถูกต้อง ในขณะที่โค้ดทำงาน (runtime)

Type Guards ที่มีประโยชน์:

1. typeof operator

ts
function processValue(val: unknown) {
  if (typeof val === "string") {
    // TypeScript รู้ว่า val เป็น string ในบล็อกนี้
    return val.toLowerCase();
  } else if (typeof val === "number") {
    // TypeScript รู้ว่า val เป็น number ในบล็อกนี้
    return val.toFixed(2);
  }
  return String(val);
}

2. Custom Type Guards ด้วย Type Predicates

ts
function isArray<T>(value: unknown): value is T[] {
  return Array.isArray(value);
}

function processItems<T>(items: unknown) {
  if (isArray<T>(items)) {
    // TypeScript รู้ว่า items เป็น T[] ในบล็อกนี้
    return items.length;
  }
  return 0;
}

3. instanceof operator

ts
class Bird {
  fly() {
    console.log("flying");
  }
}

class Fish {
  swim() {
    console.log("swimming");
  }
}

function move(pet: Bird | Fish) {
  if (pet instanceof Bird) {
    pet.fly(); // TypeScript รู้ว่า pet เป็น Bird
  } else {
    pet.swim(); // TypeScript รู้ว่า pet เป็น Fish
  }
}

Type Casting (การแปลง type)

TypeScript สามารถแปลง type ได้ 2 วิธี

1. as syntax

ts
// แปลง type ด้วย as
let someValue: unknown = "Hello World";
let strLength: number = (someValue as string).length;

// ตัวอย่างการใช้งานจริงกับ DOM Elements
const form = document.getElementById("registration-form");
const emailInput = document.querySelector("#email") as HTMLInputElement;
const passwordInput = document.querySelector("#password") as HTMLInputElement;

form?.addEventListener("submit", (e) => {
  e.preventDefault();
  const userData = {
    email: emailInput.value, // สามารถเข้าถึง .value ได้เพราะเรา cast เป็น HTMLInputElement
    password: passwordInput.value,
  };
  // ส่งข้อมูลไปยัง server
});

2. Angle bracket syntax

ts
// แปลง type ด้วย <> (ไม่แนะนำใน JSX)
let someValue: unknown = "Hello World";
let strLength: number = (<string> someValue).length;

// ตัวอย่างการใช้งานจริง
interface ApiResponse {
  data: unknown;
  status: number;
}

function processResponse(response: ApiResponse) {
  const userData = <{ name: string; email: string }> response.data;
  console.log(`User: ${userData.name}, Email: ${userData.email}`);
}

ข้อควรระวัง: การ cast type ไม่มีการตรวจสอบที่ runtime จึงอาจเกิด error ได้ถ้า cast ผิด type

Type Assertion (การยืนยัน type)

Type Assertion ใช้เมื่อเราทราบ type ของตัวแปรดีกว่า TypeScript

ts
// ตัวอย่างการใช้งานจริงกับข้อมูลจาก API
interface User {
  id: number;
  name: string;
  email: string;
}

async function fetchUser(id: number) {
  const response = await fetch(`/api/users/${id}`);
  const data = await response.json();

  // เรารู้ว่าข้อมูลที่ได้มาควรเป็น User แต่ TypeScript ไม่รู้
  const user = data as User;

  // สามารถใช้ properties ของ User ได้อย่างปลอดภัย
  return `${user.name} (${user.email})`;
}

// ตัวอย่างกับ Event Handlers
document.getElementById("save-button")?.addEventListener("click", (event) => {
  const target = event.target as HTMLButtonElement;
  target.disabled = true; // ป้องกันการกดซ้ำ

  // ทำงานต่อ...
});