this Types & Polymorphism
this ก็เป็น type ด้วย
หัวข้อที่มีชื่อว่า “this ก็เป็น type ด้วย”ภายใน class this ไม่ได้เป็นแค่ value — เป็น type ที่หมายถึง “type ของ instance ปัจจุบัน” และที่สำคัญคือใน subclass this หมายถึง subclass ไม่ใช่ class ที่ method นั้นถูกเขียนไว้ นี่คือ polymorphic this type และทำให้ fluent API ทำงานถูกต้องข้าม inheritance
fluent chaining ด้วย polymorphic this
หัวข้อที่มีชื่อว่า “fluent chaining ด้วย polymorphic this”builder ที่ return this จากแต่ละ method ทำให้ call ต่อกันเป็น chain ได้ การ type return เป็น this (ไม่ใช่ชื่อ class) แปลว่า method ของ subclass ยัง chain ต่อได้
class QueryBuilder { private parts: string[] = []; where(cond: string): this { // return type is `this`, not QueryBuilder this.parts.push(cond); return this; }}
class MySQLBuilder extends QueryBuilder { limit(n: number): this { return this; }}
new MySQLBuilder() .where("a = 1") // returns MySQLBuilder (because of `this`), so... .limit(10); // ...limit() is still available. ✅ถ้า where ถูก type ให้ return QueryBuilder chain จะ “ลืม” ว่าเป็น MySQLBuilder และ .limit() จะ fail polymorphic this รักษา type จริงไว้ตลอด chain
this parameter
หัวข้อที่มีชื่อว่า “this parameter”function สามารถ declare parameter ตัวแรกปลอม ๆ ชื่อ this เพื่อ type ว่า this ต้องเป็นอะไรตอน function ถูกเรียก parameter นี้ถูก erase ตอน emit และไม่กระทบ argument list จริง มีไว้ type-check calling context ล้วน ๆ
interface Card { title: string; }
function render(this: Card) { return this.title.toUpperCase();}
// render(); // ❌ The 'this' context of type 'void' is not assignable...render.call({ title: "hi" }); // ✅ this is a Card hereอันนี้จับ bug ทั้งกลุ่มที่ method พึ่ง this ที่อาจไม่ได้รับจริง
pitfall เรื่องเสีย this ใน type
หัวข้อที่มีชื่อว่า “pitfall เรื่องเสีย this ใน type”footgun คลาสสิกของ JavaScript — ส่ง method เป็น callback แล้วเสีย this — มีเรื่องราวระดับ type ด้วย เมื่อคุณส่ง obj.method แบบ by reference this binding จะหลุด
class Counter { count = 0; increment() { this.count++; } // relies on `this`}
const c = new Counter();const fn = c.increment;// fn(); // 💥 at runtime `this` is undefinedTypeScript จับอันนี้ได้เมื่อคุณ opt in ตัว strictBindCallApply และ (ด้วย this parameter) checker จะ flag การเรียก method ที่ไม่ได้ bind วิธีแก้แบบ idiomatic คือใช้ arrow-function field (increment = () => { ... } ซึ่ง bind this แบบ lexical) หรือ bind ที่จุดเรียก (c.increment.bind(c))