การวิเคราะห์แบบคงที่เป็นการทดสอบประเภทหนึ่งที่มีการตรวจสอบโค้ดแบบอัตโนมัติ โดยไม่ต้องเรียกใช้จริงหรือไม่ต้องเขียนการทดสอบอัตโนมัติ คุณอาจเคยเห็นการทดสอบประเภทนี้ไปแล้ว หากใช้ IDE อย่างเช่น VSCode การตรวจสอบประเภทที่ดำเนินการโดย TypeScript เป็นการวิเคราะห์แบบคงที่และอาจแสดงเป็นเส้นบิดเบี้ยวภายใต้ข้อผิดพลาดหรือคำเตือน
ESLint
ESLint เป็นเครื่องมือที่สามารถให้ความคิดเห็นเกี่ยวกับปัญหาที่อาจเกิดขึ้นในฐานของโค้ด ปัญหาเหล่านี้อาจเป็นไปได้ว่าปลอดภัย แต่ข้อผิดพลาดหรือลักษณะการทำงานที่ไม่เป็นไปตามมาตรฐานนั้นเกิดขึ้นเอง ESLint ให้คุณใช้กฎจำนวนหนึ่งที่มีการตรวจสอบในฐานของโค้ด รวมทั้งหลายกฎในชุด "แนะนำ"
ตัวอย่างที่ดีของกฎ ESLint คือกฎ no-unsafe-finally
ซึ่งป้องกันไม่ให้คุณเขียนคำสั่งที่แก้ไขขั้นตอนการควบคุมโปรแกรมภายในบล็อก finally
นี่เป็นกฎที่ดี เพราะการทำเช่นนี้เป็นวิธีแปลกๆ ในการเขียน JavaScript ซึ่งยากต่อการควบคุม แต่กระบวนการตรวจทานโค้ดที่ดีควรตรวจพบได้
try {
const result = await complexFetchFromNetwork();
if (!result.ok) {
throw new Error("failed to fetch");
}
} finally {
// warning - this will 'overrule' the previous exception!
return false;
}
ดังนั้น ESLint จึงไม่ใช่สิ่งที่มาแทนกระบวนการตรวจสอบที่มีประสิทธิภาพ (และคู่มือแนะนำรูปแบบที่ระบุว่าโค้ดเบสควรมีลักษณะอย่างไร) เนื่องจากนักพัฒนาซอฟต์แวร์ไม่ได้สามารถบันทึกแนวทางแบบนอกรีตดอกซ์ทั้งหมดที่นักพัฒนาซอฟต์แวร์อาจพยายามใส่ไว้ในฐานของโค้ดได้ คู่มือแนวทางปฏิบัติด้านภาษาอังกฤษของ Google มีส่วนสั้นๆ เกี่ยวกับ "การทำให้ใช้งานได้ง่าย"
ESLint ให้คุณละเมิดกฎและใส่คำอธิบายประกอบโค้ดเป็น "อนุญาต" ได้ ตัวอย่างเช่น คุณอนุญาตตรรกะก่อนหน้านี้ได้ด้วยการใส่คำอธิบายประกอบดังนี้
finally {
// eslint-disable-next-line no-unsafe-finally
return false;
}
หากคุณพบว่าตัวเองทำผิดกฎอยู่เรื่อยๆ ให้ลองปิดใช้งาน เครื่องมือเหล่านี้ สนับสนุนให้คุณเขียนโค้ดในลักษณะใดลักษณะหนึ่ง แต่ทีมของคุณอาจเคยชินกับการเขียนโค้ดด้วยวิธีอื่นและทราบดีถึงความเสี่ยงของวิธีดังกล่าวแล้ว
สุดท้าย การเปิดใช้เครื่องมือวิเคราะห์แบบคงที่ในฐานของโค้ดขนาดใหญ่อาจสร้างข้อผิดพลาดที่ไม่เป็นประโยชน์ (และงานที่ยุ่งจนต้องเปลี่ยนโครงสร้างภายใน) มากกว่าโค้ดที่ปกติดี จึงเป็นเรื่องง่ายที่จะเปิดใช้ตั้งแต่ช่วงแรกของวงจรโปรเจ็กต์
ปลั๊กอิน ESLint สำหรับการสนับสนุนเบราว์เซอร์
คุณสามารถเพิ่มปลั๊กอินลงใน ESLint เพื่อแจ้งการใช้งาน API ที่ไม่มีการรองรับอย่างกว้างขวางหรือไม่รองรับโดยรายการเบราว์เซอร์เป้าหมายได้ แพ็กเกจ eslint-plugin-compat จะเตือนให้คุณทราบเมื่อ API อาจไม่พร้อมใช้งานสำหรับผู้ใช้ คุณจึงไม่จำเป็นต้องติดตามดูอยู่เสมอ
การตรวจสอบประเภทสำหรับการวิเคราะห์แบบคงที่
เมื่อเรียนรู้ JavaScript นักพัฒนาซอฟต์แวร์ใหม่ๆ มักแนะนำให้คิดว่าเป็นภาษาที่พิมพ์ไม่ค่อยดี กล่าวคือ คุณสามารถประกาศตัวแปรเป็นประเภทหนึ่ง จากนั้นจึงใช้ตำแหน่งเดียวกันสำหรับสิ่งที่แตกต่างไปโดยสิ้นเชิง ซึ่งคล้ายกับ Python และภาษาสคริปต์อื่นๆ แต่ต่างจากภาษาที่คอมไพล์ เช่น C/C++ และ Rust
ภาษาประเภทนี้อาจดีสำหรับการเริ่มต้นใช้งาน ซึ่งก็คงเป็นความเรียบง่ายที่ทำให้ JavaScript ได้รับความนิยมสูง แต่มักจะเป็นจุดที่ไม่ถูกต้องสำหรับโค้ดเบสบางโค้ด หรืออย่างน้อยก็เกิดจากสิ่งที่ทำให้เกิดข้อผิดพลาดที่สับสน ตัวอย่างเช่น เมื่อส่ง number
โดยคาดว่าต้องการ string
หรือประเภทออบเจ็กต์ ค่าที่พิมพ์ไม่ถูกต้องดังกล่าวจะเผยแพร่ผ่านไลบรารีต่างๆ ได้ ก่อนสุดท้ายจะทำให้เกิดความสับสน TypeError
TypeScript
TypeScript เป็นโซลูชันยอดนิยมสำหรับกรณีที่ JavaScript ขาดข้อมูลการพิมพ์ หลักสูตรนี้มีการใช้อย่างครอบคลุม และแม้ว่าจะไม่ใช่หลักสูตรใน TypeScript แต่ก็เป็นส่วนสำคัญของกล่องเครื่องมือ เนื่องจากมีการวิเคราะห์แบบคงที่
เพื่อเป็นตัวอย่างสั้นๆ โค้ดนี้ ซึ่งคาดว่าจะควรได้รับการเรียกกลับที่ยอมรับชื่อ string
และอายุ number
:
const callback = (name: string, age: string): void => {
console.info(name, 'is now', age, 'years old!');
};
onBirthday(callback);
สร้างข้อผิดพลาดต่อไปนี้เมื่อเรียกใช้ผ่าน TypeScript หรือแม้กระทั่งเมื่อวางเมาส์เหนือ IDE
bad.ts:4:12 - error TS2345: Argument of type '(name: string, age: string) => void' is not assignable to parameter of type '(name: string, age: number) => void'.
Types of parameters 'age' and 'age' are incompatible.
Type 'number' is not assignable to type 'string'.
4 onBirthday(callback);
~~~~~~~~
Found 1 error in bad.ts:4
ท้ายที่สุดแล้ว เป้าหมายของการใช้ TypeScript คือเพื่อป้องกันข้อผิดพลาดลักษณะนี้
โดยอายุควรเป็น number
ไม่ใช่ string
แต่ค่อยๆ คืบคลานเข้ามาในโปรเจ็กต์ของคุณ ข้อผิดพลาดนี้อาจตรวจพบได้ยากหากใช้การทดสอบประเภทอื่นๆ
นอกจากนี้ ระบบประเภทนี้สามารถให้ข้อเสนอแนะก่อนที่จะมีการเขียนการทดสอบ
ซึ่งจะทำให้ขั้นตอนการเขียนโค้ดง่ายขึ้นโดยการแสดงความคิดเห็นตั้งแต่เนิ่นๆ เกี่ยวกับข้อผิดพลาดเกี่ยวกับประเภทขณะพัฒนาซอฟต์แวร์ ไม่ใช่เมื่อโค้ดทำงานในที่สุด
ส่วนที่ยากที่สุดของการใช้ TypeScript คือการตั้งค่าอย่างถูกต้อง ทุกโปรเจ็กต์ต้องมีไฟล์ tsconfig.json
ซึ่งแม้ว่าเครื่องมือบรรทัดคำสั่ง tsc
จะใช้เป็นหลัก แต่ IDE เช่น VSCode ยังอ่านเครื่องมือและเครื่องมือสร้างอื่นๆ ได้อีกมากมาย ซึ่งรวมถึง Vitest ไฟล์นี้มีตัวเลือกและแฟล็กหลายร้อยรายการ และคุณสามารถค้นหาแหล่งข้อมูลดีๆ สำหรับการตั้งค่าได้ที่นี่
เคล็ดลับ TypeScript ทั่วไป
เมื่อตั้งค่าและใช้ TypeScript ผ่านไฟล์ tsconfig.json
โปรดคำนึงถึงสิ่งต่อไปนี้
- ตรวจสอบให้แน่ใจว่าได้รวมและตรวจสอบไฟล์ต้นฉบับแล้ว หากไฟล์ใดที่ "ไม่มีข้อผิดพลาด" อย่างลึกลับ นั่นอาจเป็นเพราะไฟล์นั้นยังไม่ได้รับการตรวจสอบ
- การอธิบายประเภทและอินเทอร์เฟซภายในไฟล์
.d.ts
อย่างชัดแจ้ง จะทำให้ทดสอบฐานของโค้ดได้ง่ายขึ้นโดยไม่ต้องอธิบายโดยปริยายเมื่อเขียนฟังก์ชัน การเขียนการจำลองและโค้ดเวอร์ชัน "ปลอม" จะทำได้ง่ายขึ้นเมื่ออินเทอร์เฟซที่เกี่ยวข้องชัดเจน
TypeScript โดยนัย
หนึ่งในตัวเลือกการกำหนดค่าที่มีประสิทธิภาพและคุ้มค่ามากที่สุดของ TypeScript คือแฟล็ก noImplicitAny
แต่ก็มักจะเปิดใช้งานได้ยากที่สุด
โดยเฉพาะหากคุณมีฐานของโค้ดขนาดใหญ่อยู่แล้ว (ระบบจะเปิดใช้แฟล็ก noImplicitAny
โดยค่าเริ่มต้นหากคุณอยู่ในโหมด strict
แต่ไม่ได้เปิดใช้)
การตั้งค่าสถานะนี้จะทำให้ฟังก์ชันนี้แสดงผลข้อผิดพลาด
export function fibonacci(n) {
if (n <= 1) {
return 0;
} else if (n === 2) {
return 1;
}
return fibonacci(n - 1) + fibonacci(n - 2);
}
แม้ในฐานะผู้อ่านจะค่อนข้างชัดเจนว่า n
ควรเป็นตัวเลข
TypeScript จึงไม่สามารถยืนยันได้อย่างมั่นใจ หากคุณใช้ VSCode การวางเคอร์เซอร์เหนือฟังก์ชันจะอธิบายดังต่อไปนี้
function fibonacci(n: any): any
การเรียกใช้ฟังก์ชันนี้จะสามารถส่งผ่านค่าประเภท any
(ประเภทที่อนุญาตประเภทอื่นๆ) ไม่ใช่แค่ number
การเปิดใช้แฟล็ก noImplicitAny
จะช่วยให้คุณป้องกันโค้ดประเภทนี้ระหว่างการพัฒนาได้โดยไม่ต้องเขียนการทดสอบตรรกะทางธุรกิจอย่างละเอียดสำหรับโค้ดที่ส่งผ่านประเภทข้อมูลที่ไม่ถูกต้องในที่หนึ่งๆ
วิธีแก้ไขง่ายๆ คือทำเครื่องหมายทั้งอาร์กิวเมนต์ n
และประเภทการแสดงผลของ fibonacci
เป็น number
แฟล็ก noImplicitAny
ไม่ได้ป้องกันคุณจากการเขียน any
ในฐานของโค้ดอย่างชัดแจ้ง คุณยังคงเขียนฟังก์ชันที่ยอมรับหรือแสดงผลประเภท any
ได้ เพียงแต่ช่วยให้คุณกำหนดประเภทให้กับตัวแปรทั้งหมดได้