ค้นหาเว็บไซต์

TypeScript: ประเภทผลลัพธ์มีทุกคีย์ที่ระบุไว้เป็นพารามิเตอร์


ฉันต้องการเขียนฟังก์ชันในลักษณะที่ ประเภทค่าที่ส่งกลับจะเป็นอ็อบเจ็กต์ ซึ่งมีคีย์ตรงตามที่ระบุในอาร์เรย์เป็นพารามิเตอร์ทั้งหมด นอกจากนี้คีย์เหล่านี้ทั้งหมดควรเป็นประเภท enum ที่กำหนด ฉันได้ลองทำหลายวิธีแล้ว แต่ไม่สามารถทำให้มันทำงานได้ บางทีใครบางคนอาจจะรู้ว่ามันเป็นไปได้หรือไม่ และจะทำอย่างไร

enum Status {
  TIME = 'time',
  LOCATION = 'location'
}

function getStatus(statusToGet: Status[]) {
  // This function will always return an object containing all passed in
  // status as a key and boolean as a value, e.g.
  return statusToGet.reduce((prev, stat) => {
    prev[stat] = true; // or false
    return prev;
  }, {});
}

getStatus([]) // -> {}
getStatus([Status.TIME]) // -> { time: true }
getStatus([Status.TIME, Status.LOCATION]) // -> { time: true, location: false }

เป็นไปได้ไหมที่จะพิมพ์ฟังก์ชัน getStatus ให้ถูกต้อง เพื่อให้ TS รู้ว่าคีย์ใดอยู่ในชนิดของค่าที่ส่งกลับ

คำตอบ #1

คุณสามารถใช้ประเภทที่แมปเพื่อแมปอาร์เรย์ของประเภทสตริงลิเทอรัลไปยังวัตถุได้:

enum Status {
    TIME = 'time',
    LOCATION = 'location'
}

function getStatus<T extends Status>(statusToGet: T[]): { [P in T]: boolean } {
    return null as any;
}

getStatus([]) // -> {}
getStatus([Status.TIME]) // -> { time: true }
getStatus([Status.TIME, Status.LOCATION]) // -> { time: true, location: false }

หมายเหตุ โค้ดข้างต้นจะคืนค่า { [s:string] :any} สำหรับอาร์เรย์ว่าง ถ้าไม่ได้เปิดใช้การตรวจสอบ null อย่างเข้มงวด สิ่งนี้เกิดขึ้นเพราะ T จะถูกสรุปเป็น any เพื่อแก้ไขปัญหานี้ เราสามารถใช้ประเภทตามเงื่อนไขเพื่อตรวจสอบว่า T เป็น any หรือไม่ และคืนค่า {} อย่างชัดเจน (ขอบคุณ @jcalz สำหรับการทดสอบ any จากคำตอบนี้) ซึ่งหมายความว่าอาร์เรย์ใด ๆ ของ any จะสร้าง {} แต่เนื่องจากเราคาดว่าเป็นอาร์เรย์ของค่าของ enum ไม่ใช่อาร์เรย์ของ any สิ่งนี้อาจไม่เป็นปัญหามากนัก อาจจะเป็นฟีเจอร์เลยด้วยซ้ำ

function getStatus<T extends Status>(statusToGet: T[]): true extends false & T?  {} : { [P in T]: boolean } {
     return null as any;
}