Functions
การ type function
หัวข้อที่มีชื่อว่า “การ type function”function type อธิบาย parameter และ return type เขียน inline หรือเป็น named type ก็ได้:
type BinaryOp = (a: number, b: number) => number;
const add: BinaryOp = (a, b) => a + b;// a และ b ถูก infer เป็น number จาก context — ไม่ต้อง annotateparameter รองรับ optional (?), default value และ rest:
function make(name: string, count = 1, ...tags: string[]): void { // count default เป็น 1; tags เก็บที่เหลือเข้า string[]}optional parameter x?: number เป็น number | undefined; defaulted parameter count = 1 มองจากฝั่งภายในเป็น number เฉย ๆ แต่ผู้เรียกละไว้ได้
Overload — และทำไม union มักดีกว่า
หัวข้อที่มีชื่อว่า “Overload — และทำไม union มักดีกว่า”overload ให้ function หนึ่งตัวแสดง call signature หลายแบบ เขียน signature หลายบรรทัดตามด้วย implementation หนึ่งอัน:
function len(x: string): number;function len(x: unknown[]): number;function len(x: string | unknown[]): number { return x.length;}
len("hi"); // ✅ 2len([1, 2, 3]); // ✅ 3overload ทรงพลังแต่ใช้เกินง่าย เมื่อ signature ต่างกันแค่ที่ type ของ parameter — ไม่ใช่ที่ ความสัมพันธ์ ระหว่าง parameter กับ return — union parameter ตัวเดียวเรียบง่ายและชัดกว่า:
// เรียบง่ายกว่า overload สองตัว:function len(x: string | unknown[]): number { return x.length;}หยิบ overload จริง ๆ มาใช้เฉพาะเมื่อ return type ขึ้นกับ input shape ที่รับเข้ามาในแบบที่ union แสดงไม่ได้
การ type this
หัวข้อที่มีชื่อว่า “การ type this”ใน standalone function this type ได้ด้วย parameter ตัวแรกพิเศษที่ หายไปที่ call site (เป็น compile-time เท่านั้น):
interface Button { label: string; }
function handleClick(this: Button, event: Event): void { console.log(this.label); // this เป็น Button}ช่วยจับบั๊กคลาสสิกที่ method เสีย this เมื่อถูกส่งเป็น callback เปล่า ๆ มีประโยชน์สุดกับ API แบบเก่าที่พึ่ง this; กับ arrow function และ pattern สมัยใหม่คุณจะใช้น้อยลง
กฎ void return ที่ทำทุกคนงง
หัวข้อที่มีชื่อว่า “กฎ void return ที่ทำทุกคนงง”function type ที่ return void ไม่ได้ แปลว่า “function ต้องไม่ return อะไร” แต่แปลว่า “ผู้เรียกจะเมิน return value” function ที่ return อะไรบางอย่างจึงยัง assign ให้ type ที่ return void ได้:
type Callback = () => void;
const cb: Callback = () => 42; // ✅ ได้! ค่า 42 แค่ถูกเมินflowchart LR fn["() => number (returns 42)"] -->|assignable to| target["() => void (caller ignores return)"] target --> use["callers treat result as void — safe"]
นี่แหละคือเหตุผลว่าทำไม array.forEach(x => arr.push(x)) ถึง type-check ผ่านทั้งที่ push return number: forEach ต้องการ callback แบบ void และเมินสิ่งที่ return กลับมา พอรู้กฎแล้วก็เลิกลึกลับ — แต่แทบทุกคนต้องงงกับเรื่องนี้ก่อน