3

I'm trying to get typings to work with a generic array reduce function which basically merges two objects. The following snippet is a dumped down version of the real code. Why is fl's type {} and not IFoo & IBar?

(I'm aware that this particular example can easily be replaced with a single Object.assign() call.)

const flatten = <K, T>(prev: K, x: T): K & T => {
  return Object.assign(prev, x);
};

interface IFoo {
  foo: true;
}

interface IBar {
  bar: true;
}

const fooRes: IFoo = { foo: true };
const barRes: IBar = { bar: true };

const fl = [fooRes, barRes].reduce(flatten, {});

console.log(fl); // here, fl : {}

1 Answer 1

11

The signature of reduce is

reduce<U>(callbackfn: (previousValue: U, currentValue: T, currentIndex: number, array: T[]) => U, initialValue: U): U

(T is the type parameter of the array itself.) So, faced with the code

[fooRes, barRes].reduce(flatten, {})

the type checker's job is to figure out what U is. Let's walk through its reasoning:

  1. fooRes : IFoo and barRes : IBar, so [fooRes, barRes] : (IFoo | IBar)[]
  2. Thus, the array's T ~ IFoo | IBar
  3. So flatten is being called with its T parameter set to IFoo | IBar
  4. flatten's return type (K & T) is therefore K & (IFoo | IBar)
  5. Since flatten's return type must be assignable to U, that gives us the constraint U >= (U & (IFoo | IBar)), which simplifies to U >= (IFoo | IBar)
  6. The other bit of evidence is the initialValue parameter which has a type of {}
  7. So U >= {}
  8. The least upper bound of these two constraints is {}. So the type checker infers U ~ {}.

Why doesn't it realise that the return type is IFoo & IBar? The type checker doesn't reason about the runtime behaviour of your code - that flatten's parameter takes on a variety of different types throughout the reduction. An array of type (IFoo | IBar)[] is not guaranteed to have both IFoos and IBars in it - it could just be an array of IFoos. Deducing that flattening an heterogeneous list squashes its constitutent types down would require quite a sophisticated proof, and it doesn't seem reasonable to expect a machine to be able to write such a proof for you.

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

1 Comment

Awesome answer! Really appreciate the detailed explanation.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.