简体   繁体   中英

TypeScript intersection types with array reduce

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 : {}

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 T ~ IFoo | IBar
  3. So flatten is being called with its T parameter set to IFoo | IBar 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 IFoo s and IBar s in it - it could just be an array of IFoo s. Deducing that flatten ing 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM