Announcing Partial & Required Flow utility types + catch annotations
Starting in Flow version 0.201, make an object type’s fields all optional using Partial<ObjType>
(use instead of the unsafe $Shape
), and make an object type’s optional fields required with Required<ObjType>
. Also, you can now annotate a catch
variable with mixed
.
Partial<T>
The Partial
utility type converts all of an object or interface’s fields to be optional. For example:
type Person = {
name: string,
age: number,
};
type PartialPerson = Partial<Person>;
// Above equivalent to `{name?: string, age?: number}`
const a: PartialPerson = {}; // OK
const b: PartialPerson = {name: 'George'}; // OK
const c: PartialPerson = {name: 'George', age: 123}; // OK
This utility replaces the unsafe $Shape
utility: use Partial
now instead.
Note: while this is the first time we have announced the Partial
utility type, it has existed for a while, and had the name $Partial
. You should codemod any existing $Partial
usages to Partial
. We will remove support for the old alias $Partial
from version 0.203.
No longer in love with the $Shape
of U
Why use Partial
instead of $Shape
? $Shape
allows you to unsafely use $Shape<U>
as U
in some contexts, for example:
type PersonShape = $Shape<Person>;
const personShape: PersonShape = {name: 'George'};
const person: Person = personShape; // Unsafe - doesn't have `age` prop
const age: number = person.age; // Unsafe - actually `undefined`
It is also not equivalent to itself in some contexts:
function f<U>(input: $Shape<U>): $Shape<U> {
return input; // ERROR: `U` is incompatible with `$Shape` of `U`
}
Partial
does not have any of these problems - use it instead!
We will remove support for $Shape
from version 0.203 or later.
Required<T>
The Required
utility type is the opposite of Partial
: it converts all of an object or interface’s optional fields to be required. For example:
type PartialPerson = {
name?: string,
age?: number,
};
type Person = Required<PartialPerson>;
// Above equivalent to `{name: string, age: number}`
const a: Person = {name: 'George', age: 123}; // OK
const b: Person = {age: 123}; // ERROR: missing `name` property
Migrate your $Shape
and $Partial
usage
We will remove support for $Shape
from version 0.203 or later. You should codemod any instances of it to Partial
. This may cause new errors, due to the safety issues of $Shape
described above. In some contexts $ReadOnly<Partial<T>>
may be a better replacement for $Shape<T>
, you can try and see if that causes less errors than just Partial<T>
.
You can either use flow-upgrade
or just regular expressions to codemod your codebase.
Flow upgrade:
Get at least version 2.2.0 of flow-upgrade and run
$Shape
toPartial
:yarn run flow-codemod convertShapeToPartial
$Partial
toPartial
:yarn run flow-codemod renamePartial
Regular expressions:
$Shape
toPartial
:sed -i 's/\$Shape</Partial</g'
$Partial
toPartial
:sed -i 's/\$Partial</Partial</g'
Bonus feature: Catch variable annotations
You can now annotate catch
variables as exactly either any
or mixed
. Without an annotation they continue to be typed as any
as before. By using mixed
, you can improve your safety and Flow coverage, at the trade-off of increased runtime checks:
try {
danger();
} catch (e: mixed) {
if (e instanceof MyError) {
handleMyError(e);
} else if (e instanceof Error) {
handleError(e);
} else {
throw e;
}
}
You can choose to make mixed
the default type of catch variables by enabling the option use_mixed_in_catch_variables=true
in your .flowconfig [docs].