Generics
ปัญหาที่ generics มาแก้
หัวข้อที่มีชื่อว่า “ปัญหาที่ generics มาแก้”สมมติคุณอยากได้ function ที่คืนค่าอะไรก็ตามที่คุณส่งเข้าไป ถ้าไม่มี generics คุณจะเจอทางเลือกที่แย่ทั้งคู่:
// Option A: one type only — not reusablefunction identityStr(x: string): string { return x; }
// Option B: any — reusable, but throws away all type informationfunction identityAny(x: any): any { return x; }
const a = identityAny(42);a.toUpperCase(); // 💥 no error at compile time — any hides the bugany ทำให้ function reuse ได้ก็จริง แต่ทำให้ compiler ตาบอด — ความเชื่อมโยงระหว่าง type ของ input กับ output หายไปหมด Generics เก็บความเชื่อมโยงนั้นไว้
function identity<T>(x: T): T { return x; }
const n = identity(42); // T inferred as number → n: numberconst s = identity("hi"); // T inferred as string → s: stringn.toUpperCase(); // ❌ Error: number has no toUpperCase — the bug is caughtT คือ type parameter — ตัวยึดที่ผู้เรียก (หรือ inference) เป็นคนเติมค่าให้ function ตัวนี้ทำงานได้กับทุก type และ return type ก็ยังตาม type ของ argument ได้เป๊ะ
จริง ๆ แล้ว generics คืออะไร
หัวข้อที่มีชื่อว่า “จริง ๆ แล้ว generics คืออะไร”generic คือ function ในระดับ type — รับ type เป็น input แล้วผลิต type เป็น output identity<T> บอกว่า “สำหรับ type T ใด ๆ ก็ตาม รับ T แล้วคืน T” อันนี้เรียกว่า parametric polymorphism — implementation เดียว ที่ parameterize ด้วย type
flowchart LR impl["generic เดียว identity ของ T"] --> callN["เรียกด้วย number คืน number"] impl --> callS["เรียกด้วย string คืน string"] impl --> callU["เรียกด้วย User คืน User"]
โมดูลนี้ครอบคลุมอะไรบ้าง
หัวข้อที่มีชื่อว่า “โมดูลนี้ครอบคลุมอะไรบ้าง”| บทเรียน | สิ่งที่คุณจะได้เรียน |
|---|---|
| Functions & constraints | type parameter, constraint ด้วย extends, default type parameter |
| Classes & interfaces | generic class, interface และ type parameter ต่อ method |
| Conditional types | T extends U ? X : Y และการ distribute ผ่าน union |
Inference & infer | type argument ถูก infer อย่างไร และการดึง type ออกด้วย infer |