It is recommended to use exact object types wherever possible as it improves type checking. It is considered safe to pass an object with extra properties where a normal object type is expected in Flow. So when we add type for an object, for example:
let obj: { prop: string } = { prop : "someValue" }
This object obj
can even be assigned with more extra properties like this.
obj = { prop : "someValue", prop2: "someOtherValule" } // fine, no typechecking errors
Flow wont throw any typechecking error here. This is because { prop : "someValue", prop2: "someOtherValule" }
is subtype of { prop : "someValue" }
.
Here we can see that this is not a proper and accurate type checking as we might need to know what all properties/methods are present in an object. This is why exact object types are preferred as exact object types disable this subtyping and disallow extra properties.
let obj: { | prop: string | } = { prop : "someValue" } // ok
obj = { prop : "someValue", prop2: "someOtherValule" } // Error.
type obj = {};
type obj = { city: string };
type obj = Array<{city: string}>;
(prop: Array<{city: string}>) => {};
type obj = {| |};
type obj = {| city: string |};
type obj = { [key: string]: string };
type obj = number;
type obj = {| city: {| pin: string |} |};