การกำหนดรูปแบบตัวแปรของอ็อบเจ็กต์ในไทป์สคริปต์
ฉันกำลังพยายามกำหนดวัตถุที่สามารถมีข้อมูลหรือข้อผิดพลาดได้
export type ActionResult = {
data: any;
} | {
error: any;
};
function test():ActionResult {
return {
data: 3
}
}
เมื่อพยายามเข้าถึงผลลัพธ์ของฟังก์ชัน ฉันได้รับ:
const v = test();
v.data = 23; // Property 'data' does not exist on type 'ActionResult'. Property 'data' does not exist on type '{ error: any; }'
วิธีที่ถูกต้องในการเข้าถึง 'data' หรือ 'error' คืออะไร?
คำตอบ #1
นี่คือวิธีที่ TypeScript เข้าใจโค้ดของคุณ:
const v = test();
// v: {data: any} | {error: any}
v.data = 23;
// It is possible that 'v' is of type '{error: any}'
// In this case, an error might happen at runtime
// This error must be prevented right now - time to throw a TS error!
วิธีหนึ่งในการทำให้แน่ใจว่าสิ่งนี้จะไม่เกิดขึ้นคือการใช้ตัวป้องกันชนิด (type guard) เพื่อจำกัดชนิดของ union ให้เป็นชนิดที่ไม่ทำให้เกิดข้อผิดพลาด TS:
const v = test();
// v: {data: any} | {error: any}
if ('data' in v) {
// v: {data: any}
v.data = 23;
// no error!
}
คุณยังสามารถบอก TypeScript ได้ด้วยว่าคุณมั่นใจว่า v จะมี data โดยการแปลงชนิดของ v เมื่อกำหนดมัน:
const v = (test() as {data: any});
v.data = 23;
ตรวจสอบโค้ดนี้บน TypeScript Playground
คำตอบ #2
นี่คือวิธีแก้ปัญหาด้วยการรวมแบบ discriminated union (ฉันได้เพิ่มคุณสมบัติทั่วไป dataType ให้กับสมาชิกแต่ละรายการของ union แล้ว):
export type ActionResult = {
dataType: "value",
data: any
} | {
dataType: "error",
error: any
};
function test():ActionResult {
return {
dataType: "value",
data: 3
}
}
const v = test();
if ("value" === v.dataType){
v.data = 23;
}
