When creating an intersection of two types, and spreading the "rest props" of that object value, flow does not track the properties with in the spread object properly.
However, if I merge the two types that I was creating an intersection with, the behavior is correct. The documentation implies that an intersection type should provide the intended typing, so this may be a bug with [email protected]?
This try flow demonstrates the issue.
EDIT: I should also note, this does not error on 0.53 or 0.53.1 and could be related to the Made rest parameters in object destructuring patterns sealed, and exact if possible update in 0.54?
It seems to take only the left-most type into account, so when take for instance this example:
type Foo ={ a: number }
type Bar ={ b: number }
type Baz ={ c: number }
type Intersection = Foo & Bar & Baz;
let x:Intersection = {a: 1, b: 2, c: 3};
// error on this line because it assumes spreading x will only result in the property "a"
let y:Intersection = {...x};
If you reorder the type definition to Bar & Foo & Baz it'll think spreading x will result in the property b
Spread without exact object types won't work either as props from your example will have a type of mixed | Array<number>.
Flow can only track rested properties with exact object types.
Also, you can't intersect exact types. Semantically, this would yield an empty type.
Cannot get
props.valuesbecause propertyvaluesis missing inprops.
But, you can spread your exact object types together in an exact object type:
type A = {|
firstName: string,
|};
type B = {|
lastName: string,
|};
type C = {|
...A,
...B
|};
function test({ firstName, ...props }: C): B {
return props; // type of props is B
}
This behaviour seems to have changed in more recent versions of flow (I'm using 0.68.0 now). If I test my given example again it correctly shows the type of Intersection to be {a: number, b: number, c:number}
Most helpful comment
Spread without exact object types won't work either as
propsfrom your example will have a type ofmixed | Array<number>.Flow can only track rested properties with exact object types.
Also, you can't intersect exact types. Semantically, this would yield an empty type.
But, you can spread your exact object types together in an exact object type:
Your fixed example.