Generics ใน TypeScript
Generics ใน TypeScript
Section titled “Generics ใน TypeScript”Generics ช่วยให้เราสร้าง reusable code ที่ทำงานกับหลาย type ได้โดยไม่ต้องเสีย type safety
Generic Functions
Section titled “Generic Functions”// ไม่มี generics — ต้องเขียนหลาย functionfunction getFirstString(arr: string[]): string { return arr[0]; }function getFirstNumber(arr: number[]): number { return arr[0]; }
// มี generics — function เดียวใช้ได้กับทุก typefunction getFirst<T>(arr: T[]): T { return arr[0];}
const name = getFirst(["Alice", "Bob"]); // type: stringconst score = getFirst([95, 88, 72]); // type: number// JS ไม่มี generics — ใช้ function เดียวแต่ไม่มี type safetyfunction getFirst(arr) { return arr[0]; }from typing import TypeVar, ListT = TypeVar('T')def get_first(arr: List[T]) -> T: return arr[0]-- SQL ไม่มี concept ของ generics โดยตรง-- ใช้ UNION ALL สำหรับ polymorphic queriesSELECT column_value FROM table_name LIMIT 1;Multiple Type Parameters
Section titled “Multiple Type Parameters”// สอง type parametersfunction makePair<A, B>(first: A, second: B): [A, B] { return [first, second];}
const pair = makePair("hello", 42); // type: [string, number]
// Map functionfunction mapArray<T, U>(arr: T[], fn: (item: T) => U): U[] { return arr.map(fn);}
const lengths = mapArray(["hi", "hello"], s => s.length); // number[]Generic Interfaces
Section titled “Generic Interfaces”// API Response wrapperinterface ApiResponse<T> { data: T; status: number; message: string; timestamp: Date;}
interface User { id: number; name: string; }interface Product { id: number; title: string; price: number; }
// ใช้ generic interface กับต่าง typeconst userResponse: ApiResponse<User> = { data: { id: 1, name: "สมชาย" }, status: 200, message: "success", timestamp: new Date()};
const productResponse: ApiResponse<Product[]> = { data: [{ id: 1, title: "Laptop", price: 35000 }], status: 200, message: "success", timestamp: new Date()};Constraints ด้วย extends
Section titled “Constraints ด้วย extends”// จำกัดว่า T ต้องมี property "length"function logLength<T extends { length: number }>(item: T): void { console.log(`Length: ${item.length}`);}
logLength("hello"); // OK — string มี lengthlogLength([1, 2, 3]); // OK — array มี length// logLength(42); // Error — number ไม่มี length
// จำกัดว่า K ต้องเป็น key ของ Tfunction getProperty<T, K extends keyof T>(obj: T, key: K): T[K] { return obj[key];}
const user = { name: "Alice", age: 25 };const name = getProperty(user, "name"); // type: string// getProperty(user, "email"); // Error! "email" ไม่ใช่ key ของ userCommon Patterns
Section titled “Common Patterns”// Generic ใน React-like component propsinterface ListProps<T> { items: T[]; renderItem: (item: T) => string; onSelect?: (item: T) => void;}
// Generic classclass DataStore<T extends { id: number }> { private items: T[] = [];
add(item: T): void { this.items.push(item); } findById(id: number): T | undefined { return this.items.find(item => item.id === id); } getAll(): T[] { return [...this.items]; }}
const userStore = new DataStore<User>();userStore.add({ id: 1, name: "สมชาย" });