Performance & Pitfalls
type มี cost ตอน compile
หัวข้อที่มีชื่อว่า “type มี cost ตอน compile”การ type check คือการคำนวณจริง และ type ที่ฉลาดเกินไปทำให้ tsc คลานหรือ editor หน่วงได้ type system (ที่ขึ้นชื่อว่า) ทรงพลังพอที่จะเป็นภาษาโปรแกรมของตัวเอง — และเหมือน runtime code คือเขียนแบบที่ evaluate แพงได้เหมือนกัน
ตัวการที่พบบ่อย:
- union ขนาดใหญ่ union ของ string literal เป็นพัน ๆ ตัว (มักถูก generate) ทวีคูณงานทุกที่ที่ถูกใช้
- recursion ลึก recursive conditional/mapped type ที่เดิน tuple หรือ string ยาว ๆ ชน exponential blow-up และ instantiation-depth limit
- distributive conditional บน union ใหญ่ conditional type distribute บนทุก member — บน union ใหญ่ก็คือ instantiation จำนวนมาก
- inference ที่ทำงานหนักเกินไป API ที่ generic มากบังคับให้ checker แก้หา type argument หลายตัวในทุก call
คุณมักไม่สังเกตจนกว่าไฟล์หนึ่งใช้เวลา check เป็นวินาที หรือ red squiggle ใน editor ตามการพิมพ์ไม่ทัน นั่นคือสัญญาณให้มองที่ type ไม่ใช่แค่ code
footgun ที่พบบ่อย
หัวข้อที่มีชื่อว่า “footgun ที่พบบ่อย”นอกจาก performance เหล่านี้กัดทีมจริง:
- type ฉลาดเกินจนไม่มีใครอ่านออก conditional type 40 บรรทัดที่ประหยัด duplicate ไปสามบรรทัด มักขาดทุนสุทธิ ความฉลาดคือ cost ที่ผู้อ่านในอนาคตทุกคนต้องจ่าย
anyleakanyตัวเดียวลาม:any.fooเป็นanyจึงปิดการ check เงียบ ๆ ทุกที่ที่แตะ แบนด้วยnoImplicitAnyและ lint rule- cast ที่โกหก
x as Fooบอก compiler ให้เลิก check — ถ้าxไม่ใช่Fooจริง คุณเพิ่งซ่อน bug ไว้ double cast (x as unknown as Foo) คือธงแดงขนาดยักษ์ - เรื่องเซอร์ไพรส์ของ enum numeric
enumยอมให้ number อะไรก็ได้เป็น value และ emit runtime code;constobject กับas constหรือ string-literal union มักชัดกว่าและถูกกว่า - ใช้
asเกินจำเป็น การคว้าasมา silence error มักหมายความว่าคุณเลิก model ปัญหาแล้วเริ่มเถียงกับ compiler
flowchart LR src["one any (bad cast / JSON.parse)"] --> a1["any.user"] a1 --> a2["any.user.name"] a2 --> a3["passed to typed fn checks silently skipped"]
การ diagnose
หัวข้อที่มีชื่อว่า “การ diagnose”เมื่อการ check รู้สึกช้า ให้วัดแทนการเดา:
tsc --extendedDiagnosticsพิมพ์ว่าเวลาและ memory ไปไหน (check time, instantiation count, memory)tsc --generateTrace traceDirสร้าง trace ที่เปิดใน profiler เพื่อหา type ที่แพงได้- bisect: comment type ที่สงสัยออกแล้วดูตัวเลขขยับ
การแก้เกือบทุกครั้งคือ simplify: แทน conditional type ที่วีรบุรุษด้วย union ธรรมดา, แตก type ยักษ์เป็นชิ้นเล็กที่มีชื่อ หรือยอมรับ type ที่หลวมกว่านิดหน่อยแต่ถูกกว่า 10 เท่าและปลอดภัยพอ ๆ กันในทางปฏิบัติ