tsconfig, Deep
เริ่มจาก strict
หัวข้อที่มีชื่อว่า “เริ่มจาก strict”tsconfig.json มี option เป็นสิบ ๆ ตัว แต่มีไม่กี่ตัวที่ตัดสินว่า TypeScript ปกป้องคุณจริงหรือเปล่า ตัวสำคัญที่สุดคือ strict ไม่ใช่ check ตัวเดียว — แต่เป็นชุดที่เปิด flag ทั้งครอบครัวพร้อมกัน และทุกตัวจับ bug จริงได้
{ "compilerOptions": { "strict": true, "target": "ES2022", "module": "NodeNext", "moduleResolution": "NodeNext", "lib": ["ES2022"], "noUncheckedIndexedAccess": true, "exactOptionalPropertyTypes": true, "noImplicitOverride": true, "verbatimModuleSyntax": true }}เปิด strict ตั้งแต่วันแรก การมาเปิดทีหลังบน codebase ใหญ่ ๆ แปลว่าต้องแก้ error เป็นร้อยพร้อมกัน — ยากกว่าการไม่ปล่อยให้ error สะสมตั้งแต่แรกมาก
strict เปิดอะไรให้จริง ๆ
หัวข้อที่มีชื่อว่า “strict เปิดอะไรให้จริง ๆ”strict: true เป็นตัวย่อของครอบครัวนี้ทั้งหมด:
Flag (อยู่ใน strict) | สิ่งที่จับได้ |
|---|---|
strictNullChecks | null และ undefined ไม่แอบอยู่ในทุก type อีกต่อไป — คุ้มที่สุด |
noImplicitAny | value ที่จะ fall back เป็น any กลายเป็น error ที่คุณต้องแก้ |
strictFunctionTypes | parameter ของ function ถูก check แบบ contravariant — callback ที่ไม่ปลอดภัยถูกจับ |
strictBindCallApply | bind, call และ apply ถูก type-check กับ signature ของ function |
strictPropertyInitialization | field ของ class ต้องถูก assign ใน constructor (หรือ mark เป็น optional) |
useUnknownInCatchVariables | catch (e) ให้ unknown ไม่ใช่ any บังคับให้คุณ narrow |
alwaysStrict | emit "use strict" และ parse ใน strict mode |
พระเอกคือ strictNullChecks ถ้าไม่เปิด string จะแอบรวม null และ undefined ไว้ด้วย และ compiler เตือนคุณเรื่อง runtime crash ที่พบบ่อยที่สุดใน JavaScript ไม่ได้เลย พอเปิดแล้ว null และ undefined กลายเป็น type ของตัวเองที่คุณต้องจัดการอย่างตั้งใจ
target, module และ lib
หัวข้อที่มีชื่อว่า “target, module และ lib”สาม option นี้อธิบายโลกที่ code ของคุณรันอยู่:
target— JavaScript version ที่tscemit ออกมาES2022เป็น default สมัยใหม่ที่ปลอดภัย ถ้า target ต่ำกว่าจะ down-level syntax ใหม่ ๆ ให้เป็นของเทียบเท่าเวอร์ชันเก่าmodule— module format ของ output (NodeNext,ESNext,CommonJS, …) ควรตรงกับวิธีที่ code ถูกโหลดจริงlib— type declaration built-in ตัวไหนที่ใช้ได้ (เช่นDOMสำหรับ global ของ browser,ES2022สำหรับ method ใหม่ ๆ ของ runtime) ถ้าคุณใช้structuredCloneหรือArray.prototype.atตัวlibต้องรวมเวอร์ชันที่ declare API เหล่านั้นไว้
flag ข้าง ๆ strict ที่ควรเพิ่ม
หัวข้อที่มีชื่อว่า “flag ข้าง ๆ strict ที่ควรเพิ่ม”strict เป็นพื้น ไม่ใช่เพดาน อีกสอง flag จับ bug ที่ strict อย่างเดียวพลาด:
// noUncheckedIndexedAccess: trueconst arr = [1, 2, 3];const x = arr[10]; // type is now `number | undefined`, not `number`x.toFixed(); // ❌ Object is possibly 'undefined' — exactly the bug you want caughtnoUncheckedIndexedAccess— การ index array หรือ record อาจ returnundefinedได้ (index 10 ของ array 3 ตัวก็ return) type จึงสะท้อนความจริงนั้น มีประสิทธิภาพมากในการกัน bug out-of-boundsexactOptionalPropertyTypes— แยกความต่างระหว่าง property ที่ set เป็นundefinedกับ property ที่หายไปเลย ทำให้ optionalname?: stringไม่แอบรับname: undefinedอีกต่อไป