Dark mode
Type System (ระบบ type ข้อมูล)
ระบบ type ข้อมูลของ TypeScript ที่ช่วยตรวจสอบความถูกต้องของโค้ดขณะพัฒนาและลดข้อผิดพลาด
ระบบ Type | คำอธิบาย | ตัวอย่าง |
---|---|---|
Static Typing | ตรวจสอบ type ขณะ compile-time | let name: string = "John" |
Type Inference | อนุมาน type โดยอัตโนมัติจากค่า | let name = "John" (อนุมานเป็น string) |
Structural Typing | ตรวจสอบความเข้ากันของ type จากโครงสร้าง | Object ที่มีโครงสร้างตรงกันสามารถใช้แทนกันได้ |
Type Guard | ตรวจสอบ type ขณะ runtime | if (typeof data === "string") |
Type Casting | แปลง type ของข้อมูล | (someValue as string) หรือ <string>someValue |
Type Assertion | ยืนยัน type เมื่อเรารู้ดีกว่า TypeScript | data 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; // ป้องกันการกดซ้ำ
// ทำงานต่อ...
});