เกิดอะไรขึ้น
เราพบบั๊กที่ email ของผู้ใช้ไม่แสดงในหน้าหนึ่ง ทั้งที่ข้อมูลมาครบ สาเหตุคือโค้ดเขียนว่า user?.emial สะกดผิดหนึ่งตัว ไม่มี error ไม่มี warning และหน้าแค่แสดงค่าว่าง
บั๊กแบบนี้หลุดไปถึง production ได้ง่าย เพราะไม่มีอะไรพังให้เห็น
ทำไมถึงเป็นแบบนั้น
ถ้า user เป็น any compiler จะยอมให้เข้าถึง property อะไรก็ได้ และผลลัพธ์ก็เป็น any ด้วย ส่วน ?. แค่ช่วยให้ไม่ throw เมื่อค่าเป็น null หรือ undefined ไม่ได้ตรวจชื่อ property และที่ runtime property ที่ไม่มีอยู่ก็แค่ได้ undefined ไม่ใช่ error
ถ้า type ถูกกำหนดไว้ชัด เช่น User | null การเขียน user?.emial จะ error ว่า property นี้ไม่มีอยู่ใน type User ดังนั้นปัญหาจริงไม่ใช่ optional chaining แต่เป็น type ที่หลวมเกินไป และบางครั้งเราก็ใส่ ?. ไว้เต็มโค้ดเพราะไม่แน่ใจว่าข้อมูลหน้าตาเป็นอย่างไร
ตอนนี้เราทำอย่างไร
ให้ type ข้อมูลที่มาจากภายนอกให้ถูกต้อง เช่นใช้ interface ที่ตรงกับ response หรือ validate ด้วย schema แล้วค่อยใช้ ถ้าไม่รู้ shape จริง ให้ใช้ unknown แทน any เพื่อบังคับให้ตรวจก่อนใช้ และเปิด strict กับ noImplicitAny ไว้
ถ้าพบ ?. ซ้อนกันหลายชั้นในโค้ด ให้ถามตัวเองว่าข้อมูลส่วนนั้นควร optional จริงไหม ถ้าไม่ ให้แก้ที่ type หรือจัดการค่าว่างครั้งเดียวที่ขอบของระบบ
type User = { id: string; email: string; name?: string }
function show(a: any, b: User | null) {
a?.emial // ไม่ error: any ยอมทุกอย่าง
b?.emial // error: Property 'emial' does not exist on type 'User'
}เช็กลิสต์สั้น ๆ
- 1ค้นหา any ในโค้ดที่เกี่ยวกับข้อมูลผู้ใช้และ response ของ API
- 2แทนที่ด้วย type จริง หรือ unknown แล้ว validate
- 3เปิด strict และ noImplicitAny
- 4ลบ ?. ที่ไม่จำเป็นออกเมื่อ type บอกว่าค่านั้นต้องมีอยู่
จำไว้สั้น ๆ
ให้ type ข้อมูลให้ถูกต้องแล้ว compiler จะจับคำสะกดผิดให้ และถ้า ?. มากเกินไป ให้กลับไปดูโครงข้อมูล