2

I have an array that contains multiple objects with functions foo.

Now I want to construct a new object signature with a function foo that inherits all signatures from the array item foo functions.

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>

unfortunately, I am getting

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

This is not callable, as the signatures are conflicting.

Is there a way to get (AND instead of OR)

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

?

playground

1

1 Answer 1

3

You can use type inference in conditional types in a contravariant position to get intersections instead of unions:

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"); }

Hope that helps; good luck!

Link to code

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.