Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flowtype array of object type does not allow extra properties

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

like image 593
Balzard Avatar asked May 24 '17 10:05

Balzard


1 Answers

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.

like image 156
loganfsmyth Avatar answered Sep 21 '22 13:09

loganfsmyth