I am having a strange error with flow.
I'm simply trying to have a function that accepts an array of objects with an amount property but I'm having errors when providing objects with more properties.
const sum = (items: Array<{amount: number}>) => {/* something */}
type Item = {
  amount: number,
  name: string
};
const list: Array<Item> = [];
sum(list);
This gives me the following errors:
10: const list: Array<Item> = [];
                      ^ property `name`. Property not found in
2: const sum = (items: Array<{amount: number}>) => {/* something */}
                             ^ object type
https://flow.org/try/#0FAYw9gdgzgLgBFArgWzgXjgCgJYwKbJQBccAggE7kCGAngDwDeVyYiEMJEKARnuQL4A+AJTpBcBgHoAVAjDI8MABbYIAczjTJ-YLpg0ADnjgBJfKgwNgcOM1btOPPgBprcCMzwlY5VWuD8ANy64NDwADbYsCQU1PRmBOIYANoAusHASMiYkbDCgUA
Similar to the issue described here: https://github.com/facebook/flow/issues/1644
This is not allowed, because the declaration you have,
const sum = (items: Array<{amount: number}>) => {/* something */}
would allow
const sum = (items: Array<{amount: number}>) => {
    items.push({amount: 4});
};
which is totally valid given the declaration of items. The array passed to sum is a list of your Item type, which requires a name, which isn't set here.
As you mentioned, $ReadOnlyArray works, because it is read-only and can't have more items added to it. Alternatively you could drop the type definitions from sum entirely and let Flow infer them, or change Array<{amount: number}> to Array<*> so Flow knows it is an array, but will infer the type of the content. Another alternative (that you left in the comments) is
const sum = <T : {amount: number}>(items: Array<T>) => {/* something */}
which will set T to Item based on your call to sum(list), with the restriction that it will accept any T that is an object with a numeric amount property.
This is probably the best option.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With