Exact object types by default, by default

George Zahariev
Flow
Published in
2 min readFeb 16, 2023

We announced 5 years ago a plan to eventually make exact object types the default. We are now proceeding with this plan. Starting with Flow 0.200, you must explicitly set either exact_by_default=true or exact_by_default=false in the [options] section of your .flowconfig, as we have eliminated the default value (which was false). From Flow 0.202, a default value will be added again, this time as exact_by_default=true.

In future versions, we will take steps to make exact_by_default=true the default value if no option is set, and then eventually delete the option completely. Take a look at the “Call to action” section at the end of this post to learn how to update your codebase.

Exact object types

Exact object types permit only the properties listed - no extra properties are allowed. Inexact object types permit additional, unknown properties.

When exact_by_default=false (previously the default):

type ExplicitlyExact = {|a: number, b: string|};
type ExplicitlyInexact = {a: number, b: string, ...};
type ImplicitlyInexact = {a: number, b: string}; // Inexact

With exact_by_default=true (the future default):

type ExplicitlyExact = {|a: number, b: string|};
type ExplicitlyInexact = {a: number, b: string, ...};
type ImplicitlyExact = {a: number, b: string}; // Exact

Plan

  1. Require that exact_by_default is set in the .flowconfig, either to true or false, and error if the option is missing. From Flow 0.200
  2. Remove the above error and make the default, if the option is not specified, exact_by_default=true. From Flow 0.202
  3. Enable the implicit-inexact-object lint by default as an error (only in effect when exact_by_default=false). This requires either {|foo: T|} or {foo: T, ...}. Later this year.
  4. Delete the option and associated lints, no longer allow exact_by_default=false. Later this year.

Call to action

If you already have set exact_by_default=true in your .flowconfig, you don’t need to take any action at the moment. In the future, when the option is deleted, all you will need to do is delete that line from your .flowconfig.

If you have not set the above option at all, then to preserve the previous default behavior you can add exact_by_default=false to your .flowconfig.

We plan on completely removing the option in the future. To update your codebase so you can enable exact_by_default=true, read through this blog post from 2020. In short:

  • Install flow-upgrade (it expects prettier as a peer dependency) [npm]
  • Run yarn run flow-codemod convertImplicitInexactObjectTypes (or npm equivalent). This will convert all implicit inexact object types, e.g. {a: number, b: string}, to be explicit, e.g. {a: number, b: string, ...}
  • Enable implicit-inexact-object=error in the [lints] section in your .flowconfig [docs]
  • Fix any remaining errors that arise, until you have no errors due to the above lint
  • Change exact_by_default to true in your .flowconfig, and turn off the implicit-inexact-object lint
  • Codemod all explicitly exact object types, e.g. {|a: number|}, to remove the | (now that they are the default). Run yarn run flow-codemod removeExplicitlyExactObjectTypeSyntax (or npm equivalent) to turn that example into {a: number}

--

--