TypeScript: วิธีการใช้ type guard กับ union type
ฟังก์ชัน compose สามารถมีออบเจ็กต์หรืออาร์เรย์ของออบเจ็กต์เป็นอาร์กิวเมนต์ ใน compose ตัวตรวจสอบชนิด (type guard) จะแยกความแตกต่างระหว่างออบเจ็กต์กับอาร์เรย์ ฟังก์ชัน mapper สามารถจัดการเฉพาะออบเจ็กต์ได้เท่านั้น และโดยการใช้ตัวตรวจสอบชนิด จะมีการส่งเฉพาะออบเจ็กต์ไปให้มัน
interface Link {
something: string;
}
function compose(link: Link|Link[]) {
if (link instanceof Array) {
R.map(function(l) {
return mapper(l);
}, link);
} else {
return mapper(link);
}
}
function mapper(link: Link) {
return link;
}
การคอมไพล์ตัวอย่างนี้ทำให้เกิดข้อผิดพลาด:
ข้อผิดพลาด TS2345: อาร์กิวเมนต์ประเภท 'Link | Link[]' ไม่สามารถกำหนดค่าให้กับพารามิเตอร์ประเภท 'Link' ได้
ข้อผิดพลาดนี้สามารถเข้าใจได้เนื่องจาก mapper ได้รับประเภท union เป็นอาร์กิวเมนต์ แต่คาดหวังเพียงวัตถุเดียว นี่ไม่ใช่สิ่งที่ฉันคาดหวังเมื่อใช้ type guard มีความคิดเห็นอะไรเกี่ยวกับเรื่องนี้ไหม?
คำตอบ #1
ดูเหมือนว่า TypeScript 1.4.0.0 จะไม่สรุปว่า link ต้องเป็นชนิด Link เมื่อมันไม่ใช่ชนิด Array การเปลี่ยนแปลงเล็กน้อยน่าจะช่วยแก้ปัญหานั้นได้:
function compose(link: Link|Link[]) {
if (link instanceof Array) {
R.map(function(l) {
return mapper(l);
}, link);
} else if (link instanceof Link) {
return mapper(link);
}
}
หรือคุณอาจระบุประเภท:
return mapper(<Link> link);
