semi — เซมิโคลอน และกับดัก ASI ที่อยู่เบื้องหลังค่าเริ่มต้น
ตัวเลือก Semi ของ Prettier
semi กำหนดว่า Prettier จะปิดท้ายคำสั่งด้วยเซมิโคลอนหรือไม่ ค่าเริ่มต้นคือ true และเหตุผลไม่ได้อยู่ที่ความสวยงาม แต่เป็นเพราะการแทรกเซมิโคลอนอัตโนมัติของ JavaScript มีกรณีที่ผิดพลาดแบบคาดไม่ถึงอยู่ไม่กี่กรณี และการพิมพ์เซมิโคลอนออกมาก็ตัดกรณีเหล่านั้นออกไปจากการพิจารณาทั้งหมด
Print semicolons.- ค่าเริ่มต้น
true- ชนิด
boolean- แฟล็ก CLI
--no-semi
ออปชันนี้ทำอะไร
เมื่อ semi: true ซึ่งเป็นค่าเริ่มต้น Prettier จะปิดท้ายทุกคำสั่งที่ใส่เซมิโคลอนได้ ส่วน semi: false จะละไว้ ยกเว้นในจุดที่การละจะเปลี่ยนความหมายของโปรแกรม
ข้อยกเว้นนั้นคือหัวใจของเรื่องทั้งหมด จริง ๆ แล้ว JavaScript ไม่ได้บังคับให้ใช้เซมิโคลอน เพราะตัวแยกวิเคราะห์จะแทรกให้เองตามกฎที่เรียกว่า automatic semicolon insertion หรือ ASI ซึ่งทำงานโดยสังเกตว่าโทเคนถัดไปต่อจากคำสั่งปัจจุบันไม่ได้ แล้วจึงปิดคำสั่งนั้น กฎนี้ถูกเกือบตลอด และผิดในไม่กี่กรณีที่เจ็บหนัก
กรณีคลาสสิกคือบรรทัดที่ขึ้นต้นด้วยวงเล็บเหลี่ยมหรือวงเล็บกลม ตัวแยกวิเคราะห์จะอ่านว่าเป็นส่วนต่อของบรรทัดก่อนหน้า คือการเข้าถึงดัชนีหรือการเรียกฟังก์ชัน ไม่ใช่คำสั่งใหม่
const value = compute()
[1, 2, 3].forEach(run)
// ถูกอ่านเป็น:
const value = compute()[1, 2, 3].forEach(run)valuePrettier ทำอะไรเมื่อคุณปิดเซมิโคลอน
semi: false ใน Prettier ปลอดภัยในแบบที่โค้ดไร้เซมิโคลอนซึ่งเขียนด้วยมือไม่ปลอดภัย เมื่อบรรทัดใดจะขึ้นต้นด้วยอักขระที่ต่อเนื่องจากคำสั่งก่อนหน้า Prettier จะเติมเซมิโคลอนป้องกันไว้ข้างหน้า
const value = compute()
;[1, 2, 3].forEach(run)อักขระที่กระตุ้นพฤติกรรมนี้ได้แก่ [ ( แบ็กทิก + - / และอีกสองสามตัวที่พบไม่บ่อย คุณจะเห็นเซมิโคลอนนำหน้าแบบนี้ในโค้ดเบสไร้เซมิโคลอนทุกแห่งที่ใช้ Prettier มันดูแปลกในตอนแรกและมันไม่ใช่ของที่ตัดทิ้งได้ การลบออกด้วยมือคือการนำบั๊กที่สไตล์นี้ตั้งใจจะเลี่ยงกลับเข้ามาพอดี
ทำไมค่าเริ่มต้นถึงเป็น true
ค่าเริ่มต้นของ Prettier มักเอนไปทางตัวเลือกที่ต้องอธิบายให้ผู้มาใหม่น้อยที่สุด และเซมิโคลอนชนะการทดสอบนั้น ผู้อ่านที่ไม่เคยได้ยินเรื่อง ASI ก็อ่านโค้ดที่ปิดท้ายด้วยเซมิโคลอนได้ถูกต้อง แต่ในทางกลับกันไม่จริง เพราะสำนวนเซมิโคลอนนำหน้านั้นสับสนจริง ๆ จนกว่าจะมีคนอธิบาย
ยังมีเหตุผลเชิงปฏิบัติที่เล็กกว่าอีกข้อ เซมิโคลอนทำให้แต่ละคำสั่งกำหนดขอบเขตของตัวเองได้ บรรทัดที่ถูกย้าย ทำซ้ำ หรือสลับลำดับโดยเอดิเตอร์หรือการ merge จึงยังใช้ได้อยู่ ถ้าไม่มีเซมิโคลอน การย้ายบรรทัดอาจทำให้มันเชื่อมกับเพื่อนบ้านใหม่โดยเงียบ ๆ
เมื่อไรควรเลือก false
เหตุผลของ semi: false มีอยู่จริง เซมิโคลอนไม่ได้ให้ข้อมูลอะไรที่ตัวจัดรูปแบบหาเองไม่ได้ และโค้ดเบสที่ไม่มีมันก็แน่นน้อยกว่าบนหน้าจออย่างวัดได้ ระบบนิเวศใหญ่หลายแห่ง ทั้งสไตล์ standard และโลกของ Vue กับ Nuxt ส่วนมาก ต่างเลือกที่จะละมัน โปรเจกต์ที่อยู่ในวงโคจรเดียวกันจึงจะรู้สึกเข้าที่กว่าเมื่อทำตามเพื่อนบ้าน
- เลือก
falseถ้าทีมของคุณเขียนแบบนี้อยู่แล้ว หรือชุมชนของเฟรมเวิร์กที่ใช้เป็นแบบนั้น ความสอดคล้องกับโค้ดที่ผู้ร่วมพัฒนาอ่านจากที่อื่นมีค่ามากกว่าความปลอดภัยส่วนเพิ่ม - เลือก
trueถ้าทีมมีประสบการณ์คละกัน หรือโค้ดเบสอยู่ยาวและคุณไม่อยากต้องอธิบายเรื่องเซมิโคลอนนำหน้าในการรีวิว - อย่าเลือกจากความยากในการพิมพ์ Prettier เป็นคนเขียนมันให้ คุณไม่เคยต้องพิมพ์เองสักตัว
ESLint TypeScript และ CI
ESLint มีทั้งกฎ semi และกฎ no-unexpected-multiline และกฎแรกจะขัดกับ Prettier ถ้าเปิดทั้งคู่ ให้ปิดกฎเชิงรูปแบบด้วย eslint-config-prettier โดยวางไว้ท้ายสุดในคอนฟิก แล้วปล่อยให้ Prettier เป็นเจ้าของการตัดสินใจนี้
no-unexpected-multiline เป็นตัวที่น่าสนใจและควรเก็บไว้ถ้ามันรอดจากคอนฟิกของคุณ เพราะมันจับกับดัก ASI ข้างต้นได้ตั้งแต่ตอน lint แทนที่จะไปเจอตอนรันจริง มันไม่ใช่กฎเชิงรูปแบบจึงไม่ขัดกัน
TypeScript ไม่ได้รับผลกระทบจากการตั้งค่านี้ เซมิโคลอนเป็นทางเลือกในนั้นด้วยเหตุผลเดียวกันและมีกับดักแบบเดียวกัน การประกาศพร็อพเพอร์ตี้ของคลาสเป็นจุดเดียวที่เครื่องหมายวรรคตอนที่พิมพ์ออกมาต่างกันเล็กน้อยระหว่างสองค่านี้ และ Prettier จัดการให้แล้ว
ข้อผิดพลาดที่พบบ่อย
- ลบเซมิโคลอนนำหน้าที่ Prettier ใส่ให้ภายใต้
semi: falseมันมีหน้าที่สำคัญ - ปล่อยให้กฎ
semiของ ESLint ทำงานควบคู่กับ Prettier ซึ่งทำให้เกิดวงวนที่แก้ไม่ได้เพราะเครื่องมือทั้งสองคอยลบล้างกัน - สลับค่านี้บนโค้ดเบสที่โตแล้วโดยไม่แยกคอมมิตสำหรับการจัดรูปแบบใหม่ มันแตะเกือบทุกบรรทัดในโปรเจกต์
- เข้าใจว่า
semi: falseแปลว่าจะไม่มีเซมิโคลอนโผล่ที่ไหนเลย ลูปforยังต้องมีของมัน เพราะนั่นเป็นไวยากรณ์ ไม่ใช่ตัวปิดคำสั่ง
ใช้ใน .prettierrc
ใส่ semi ลงในไฟล์ตั้งค่า Prettier ของคุณ:
{
"semi": true
}ลองใช้ในตัวสร้างตัวอย่างจริง
โค้ดเดียวกันที่จัดรูปแบบด้วยแต่ละค่าของ semi
semi: true
const user = {
name: "Ada",
"user-id": 7,
roles: ["admin", "editor"],
active: true,
};
const greet = (name) => `Hello ${name}`;
const label = user.active
? "active member of the team"
: "inactive member of the team";
export function summarize(items) {
return items
.filter((i) => i.active)
.map((i) => i.name)
.join(", ");
}semi: false
const user = {
name: "Ada",
"user-id": 7,
roles: ["admin", "editor"],
active: true,
}
const greet = (name) => `Hello ${name}`
const label = user.active
? "active member of the team"
: "inactive member of the team"
export function summarize(items) {
return items
.filter((i) => i.active)
.map((i) => i.name)
.join(", ")
}คำถามที่พบบ่อย
- semi: false อันตรายจริงไหม
- ไม่ เมื่อ Prettier เป็นตัวเขียนโค้ดให้คุณ Prettier จะแทรกเซมิโคลอนนำหน้าเชิงป้องกันในทุกบรรทัดที่จะถูกอ่านผิด อันตรายอยู่ที่โค้ดไร้เซมิโคลอนที่เขียนด้วยมือ หรือการแก้ผลลัพธ์ของ Prettier เองแล้วลบเซมิโคลอนนำหน้าเหล่านั้นออก
- ทำไมไฟล์ของฉันขึ้นต้นบรรทัดด้วยเซมิโคลอน
- เพราะบรรทัดนั้นขึ้นต้นด้วย
[(แบ็กทิก หรือตัวดำเนินการ และถ้าไม่มีเซมิโคลอน JavaScript จะเชื่อมมันเข้ากับคำสั่งก่อนหน้า Prettier ใส่ให้โดยตั้งใจภายใต้semi: false - ออปชันนี้มีผลกับ TypeScript JSON หรือ CSS ไหม
- มีผลกับ JavaScript และ TypeScript ส่วน JSON ไม่มีคำสั่งจึงไม่เกี่ยวข้อง และการประกาศใน CSS ปิดท้ายด้วยเซมิโคลอนเสมอตามไวยากรณ์ ออปชันนี้จึงไม่มีผลที่นั่นเช่นกัน
ตัวเลือก JavaScript อื่น ๆ
สร้างจาก Prettier 3.9.6