Issue
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 : {}
Solution
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:
fooRes : IFoo
andbarRes : IBar
, so[fooRes, barRes] : (IFoo | IBar)[]
- Thus, the array's
T ~ IFoo | IBar
- So
flatten
is being called with itsT
parameter set toIFoo | IBar
flatten
's return type (K & T
) is thereforeK & (IFoo | IBar)
- Since
flatten
's return type must be assignable toU
, that gives us the constraintU >= (U & (IFoo | IBar))
, which simplifies toU >= (IFoo | IBar)
- The other bit of evidence is the
initialValue
parameter which has a type of{}
- So
U >= {}
- The least upper bound of these two constraints is
{}
. So the type checker infersU ~ {}
.
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.
Answered By - Benjamin Hodgson
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.