מיפוי TypeScript על תנאי לא מכונס: הפוך OR ל-AND


יש לי מערך שמכיל מספר אובייקטים עם פונקציות foo.

עכשיו אני רוצה לבנות חתימת אובייקט חדשה עם פונקציה foo שיורשת את כל החתימות מהפונקציות foo של פריטי המערך.

let arr = [
    { foo: (a: 'a') => 'A' as const },
    { foo: (a: 'b') => 'B' as const },
];

type MapAndUnion<T extends ReadonlyArray<any>> = { foo: T[number] extends { foo: infer V } ? V : never }

type U = MapAndUnion<typeof arr>

לצערי, אני מקבל

type U = {
    foo: ((a: "a") => "A") | ((a: "b") => "B");
}

זה לא ניתן לקריאה, מאחר שהחתימות סותרות זו את זו.

האם יש דרך לקבל (AND במקום OR)

type U = {
    foo: ((a: "a") => "A") & ((a: "b") => "B");
}

?

מִגרָשׂ מְשָׂחָק

תשובה #1

אתה יכול להשתמש בהסקת טיפוס בסוגים מותנים במיקום קונטרוואריאנטי כדי לקבל חיתוכים במקום איחודים:

type MapAndIntersection<T extends ReadonlyArray<any>> =
  { foo: ((x: T[number]) => void) extends ((x: { foo: infer V }) => void) ? V : never }

type U = MapAndIntersection<typeof arr>
// type U = { foo: ((a: "a") => "A") & ((a: "b") => "B"); }

מקווה שזה עוזר; בהצלחה!

קישור לקוד