discriminated (tagged) union คือการรวมกันของประเภทวัตถุที่ใช้ฟิลด์ literal ร่วมกัน — discriminant — ซึ่งคอมไพเลอร์ใช้เพื่อแยกความแตกต่างของตัวแปรและจำกัดอย่างปลอดภัย
=
| { : }
| { : ; : }
| { : ; : };
discriminated (tagged) union คือการรวมกันของประเภทวัตถุที่ใช้ฟิลด์ literal ร่วมกัน — discriminant — ซึ่งคอมไพเลอร์ใช้เพื่อแยกความแตกต่างของตัวแปรและจำกัดอย่างปลอดภัย
=
| { : }
| { : ; : }
| { : ; : };
สมาชิกแต่ละตัวมี status literal ตรวจสอบ จะจำกัดไปที่ตัวแปรเดียวพอดี ซึ่งจะปลดล็อกฟิลด์ของตัวแปรนั้น:
function render(r: Result) {
switch (r.status) {
case "loading": return "...";
case "success": return r.data; // ✅ data exists only here
case "error": return r.message; // ✅ message exists only here
}
}
หากคุณพยายามเข้าถึง r.data ในกรณี loading มันจะเป็นข้อผิดพลาดการคอมไพล์ — ระบบประเภททำให้ชุดค่าผสมที่ไม่ถูกต้อง ไม่สามารถแทนค่าได้
function render2(r: Result): string {
switch (r.status) {
case "loading": return "...";
case "success": return r.data;
case "error": return r.message;
default:
const _exhaustive: never = r; // ✅ if you add a variant and forget a case, this errors
return _exhaustive;
}
}
การกำหนด never บังคับให้คุณจัดการทุกกรณี — เพิ่มสถานะใหม่ และคอมไพเลอร์จะชี้ให้เห็นทุก switch ที่ต้องการการอัปเดต
Discriminated union คือวิธีมาตรฐานในการสร้างแบบจำลองสถานะ (loading/success/error) เหตุการณ์/การดำเนินการ (Redux reducers) และข้อมูล "หนึ่งในหลายรูปแบบ"
พวกเขาทำให้สถานะที่ไม่ถูกกฎหมายเป็นไปไม่ได้ และด้วยเคล็ดลับ never คุณจะได้รับการตรวจสอบความครบถ้วนสมบูรณ์ในเวลาคอมไพล์ — ชัยชนะด้านความปลอดภัยที่มหาศาลเมื่อเทียบกับการสร้างแบบจำลองด้วย boolean/optional-field ที่หลวม