การตรวจสอบความครอบคลุมทั้งหมดด้วย never
ตรวจจับกรณีที่ไม่ได้จัดการตั้งแต่เวลาคอมไพล์ด้วย never
การตรวจสอบความครอบคลุมทั้งหมดด้วย never เป็นบทเรียน TypeScript Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน TypeScript Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส TypeScript Academy มีบทเรียนทั้งหมด 4 บทเรียน
ปัญหาการจัดการให้ครบทุกกรณี
เมื่อคุณเพิ่มสมาชิกใหม่ในยูเนียน ก็อาจลืมจัดการสมาชิกนั้นในบางจุดได้ง่าย การตรวจสอบความครบถ้วนทุกกรณีจะเปลี่ยนการตกหล่นนั้นให้เป็นข้อผิดพลาดเวลาคอมไพล์
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
// If we add "triangle" later, we want every switch to complain.ชนิดเนเวอร์
ชนิด never ใช้แทนค่าที่ไม่มีทางเกิดขึ้นได้ หากจัดการทุกกรณีแล้ว ค่าที่ไปถึงแขนงเริ่มต้นจะมีชนิดเป็น never
function fail(): never {
throw new Error("unreachable");
}
// never is assignable to nothing except never itself.การกำหนดค่าให้ never ในกรณีเริ่มต้น
ในแขนง default ให้กำหนดค่าให้ตัวแปรชนิด never หากจัดการสมาชิกทุกรูปแบบแล้ว การกำหนดค่านี้จะคอมไพล์ได้ แต่หากยังไม่ครบจะเกิดข้อผิดพลาด
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
function area(s: Shape): number {
switch (s.kind) {
case "circle": return Math.PI * s.radius ** 2;
case "square": return s.side ** 2;
default:
const _exhaustive: never = s;
return _exhaustive;
}
}
console.log(area({ kind: "square", side: 3 }));จะเกิดอะไรขึ้นเมื่อลืมกรณีหนึ่ง
หากคุณเพิ่มสมาชิก triangle แต่ลืมเพิ่มกรณีของมัน s ในค่าเริ่มต้นจะไม่ใช่ never อีกต่อไป ดังนั้นการกำหนดค่าจะล้มเหลวในเวลาคอมไพล์
// type Shape = ... | { kind: "triangle"; base: number; height: number };
// Now in default, s is { kind: "triangle"; ... }
// const _exhaustive: never = s; // Error: triangle not assignable to neverตัวช่วย assertNever
ฟังก์ชัน assertNever ที่นำกลับมาใช้ซ้ำได้จะรวมรูปแบบนี้ไว้ในจุดเดียว ฟังก์ชันนี้รับค่า never และโยนข้อผิดพลาด เพื่อบันทึกให้เห็นว่าแขนงดังกล่าวไม่ควรถูกเรียกใช้งาน
function assertNever(value: never): never {
throw new Error("Unhandled case: " + JSON.stringify(value));
}
console.log(typeof assertNever);การใช้ assertNever ในสวิตช์
เรียกใช้ assertNever(s) ในกรณีเริ่มต้น ฟังก์ชันนี้บังคับให้จัดการครบทุกกรณีในเวลาคอมไพล์ และให้ข้อผิดพลาดขณะทำงานที่ชัดเจนหากมีการเข้าถึงแขนงนี้
function assertNever(value: never): never {
throw new Error("Unhandled: " + JSON.stringify(value));
}
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
function area(s: Shape): number {
switch (s.kind) {
case "circle": return Math.PI * s.radius ** 2;
case "square": return s.side ** 2;
default: return assertNever(s);
}
}
console.log(area({ kind: "circle", radius: 1 }).toFixed(2));ความปลอดภัยเวลาคอมไพล์กับขณะทำงาน
การตรวจสอบด้วย never จะตรวจจับกรณีที่ขาดหายไปก่อนที่คุณจะเรียกใช้โค้ด และข้อผิดพลาดที่ถูกโยนจะช่วยป้องกันคุณหากมีบางอย่างหลุดผ่านการตรวจสอบชนิดไปได้ขณะทำงาน
function assertNever(x: never): never {
throw new Error("Unhandled: " + String(x));
}
// Compile error if a case is missing; runtime throw as a backstop.
console.log("two layers of safety");การตรวจสอบครบทุกกรณีโดยไม่ใช้ค่าเริ่มต้น
หากฟังก์ชันของคุณมีชนิดผลลัพธ์ที่ระบุไว้อย่างชัดเจน และสวิตช์ครอบคลุมทุกกรณี TypeScript ยังสามารถแจ้งเตือนเมื่อขาดการคืนค่าได้ด้วย ซึ่งเป็นการตรวจสอบความครบถ้วนอีกแบบหนึ่ง
type Light = "red" | "yellow" | "green";
function next(l: Light): Light {
switch (l) {
case "red": return "green";
case "yellow": return "red";
case "green": return "yellow";
}
// No default needed; all cases return.
}
console.log(next("red"));การตรวจสอบครบทุกกรณีด้วยสายโซ่ if/else
แนวคิดเดียวกันนี้ใช้กับ if/else ได้เช่นกัน หลังจากจัดการสมาชิกแต่ละรูปแบบแล้ว else สุดท้ายจะได้รับค่า never
function assertNever(x: never): never { throw new Error("bad"); }
type Shape =
| { kind: "circle"; radius: number }
| { kind: "square"; side: number };
function name(s: Shape): string {
if (s.kind === "circle") return "circle";
else if (s.kind === "square") return "square";
else return assertNever(s);
}
console.log(name({ kind: "square", side: 2 }));เหตุใด never จึงเป็นเครื่องมือที่เหมาะสม
เนื่องจากไม่สามารถกำหนดค่า never ให้ชนิดอื่นได้ สมาชิกที่เหลืออยู่จึงทำให้การกำหนดค่าล้มเหลว นี่ทำให้ never เป็นตัวตรวจจับกรณีที่ยังไม่ได้จัดการได้อย่างเหมาะสม
// Only never is assignable to never.
let x: never;
// x = "hi"; // Error
// Any concrete leftover type fails the same way.
console.log("never catches gaps");ความครบถ้วนทุกกรณีในฐานะหลักประกันเมื่อปรับโครงสร้าง
เมื่อมี assertNever อยู่ทุกจุด การเพิ่มสมาชิกในยูเนียนจะสร้างรายการข้อผิดพลาดเวลาคอมไพล์ที่เป็นระเบียบ และชี้ตรงไปยังทุกจุดที่คุณต้องแก้ไข
function assertNever(x: never): never { throw new Error("unhandled"); }
type Status = "idle" | "busy";
function render(s: Status): string {
switch (s) {
case "idle": return "Idle";
case "busy": return "Busy";
default: return assertNever(s);
}
}
console.log(render("idle"));ตรวจสอบความเข้าใจ: ความครบถ้วนทุกกรณี
ตรวจสอบความเข้าใจของคุณเกี่ยวกับการตรวจสอบความครบถ้วนทุกกรณี
สรุปทบทวน: ความครบถ้วนทุกกรณีด้วยชนิดเนเวอร์
คุณได้เรียนรู้การกำหนดค่าเริ่มต้นให้เป็น never (หรือส่งค่าให้ assertNever) เพื่อให้คอมไพเลอร์บังคับให้คุณจัดการสมาชิกทุกรูปแบบ วิธีนี้เปลี่ยนกรณีที่ลืมจัดการให้กลายเป็นข้อผิดพลาดเวลาคอมไพล์
function assertNever(x: never): never { throw new Error("unhandled"); }
type Shape = { kind: "circle"; radius: number } | { kind: "square"; side: number };
function f(s: Shape) {
switch (s.kind) {
case "circle": return s.radius;
case "square": return s.side;
default: return assertNever(s);
}
}
console.log(f({ kind: "circle", radius: 5 }));คำถามที่พบบ่อย
บทเรียน “การตรวจสอบความครอบคลุมทั้งหมดด้วย never” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การตรวจสอบความครอบคลุมทั้งหมดด้วย never” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส TypeScript Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส TypeScript Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การตรวจสอบความครอบคลุมทั้งหมดด้วย never”
ตรวจจับกรณีที่ไม่ได้จัดการตั้งแต่เวลาคอมไพล์ด้วย never คุณปฏิบัติ TypeScript Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน TypeScript Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน TypeScript Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน
บทเรียน “การตรวจสอบความครอบคลุมทั้งหมดด้วย never” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน TypeScript Academy นี้ได้ไหม
ได้ บทเรียน TypeScript Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การสร้างยูเนียนแบบจำแนก
- การจำกัดชนิดข้อมูลด้วยตัวจำแนก
- การตรวจสอบความครอบคลุมทั้งหมดด้วย never
- การจำลองเครื่องสถานะ