Search code examples
javascriptflow-js

Cannot spread object literal because Flow cannot determine a type for object literal


The following (simplified) code

type Category = {
    id: string,
    name: string,
};

type Option = {
    id: string,
    name: string,
    isSelected: boolean,
};

const options = categories.map((c: Category): Option => ({
 isSelected: true,
 ...c,
}));

produces the error:

Flow: Cannot spread object literal because Flow cannot determine a type for object literal [1]. Category [2] is inexact, so it may contain isSelected with a type that conflicts with isSelected's definition in object literal [1]. Try making Category [2] exact.

What am I missing?


Solution

  • Your category type is inexact, which means that it may contain properties not defined in your type. The error shows up because if c contains a property named isSelected, it may result in an Option object not having a boolean value for that property.

    There are two possible fixes:

    const options = categories.map((c: Category): Option => ({
       ...c,
     isSelected: true,
    }));
    

    This will result in isSelected: true always taking precedence over c.isSelected if it ever existed.

    The second fix is to make Category exact.

    type Category = {|
        id: string,
        name: string,
    |};
    

    Doing this will forbid it to have extra properties. You should try to make your objects exact whenever possible.

    For more information, you can read https://flow.org/en/docs/types/objects/#toc-exact-object-types