It's a Monday after Flow updated 😱 0.98 seems to contain many fixes. Happy to see Flow making more sense version by version. I'm also glad to be learning bits and bites about Flow on the go so I thought I'd share about that :)
Release notes are here, and following are my notes. Flow please be happy 🤞
Turn the deprecated-utility lint on by default
Possible errors:
- Deprecated utility. Using
$Subtype
types is not recommended! (deprecated-utility) - Deprecated utility. Using
$Supertype
types is not recommended! (deprecated-utility)
deprecated-utility
is a lint rule that was added in 0.89. So far $Subtype
and $Supertype
are deprecated. However, Flow only starts to complain from this version because deprecated-utility
is now turned on by default.
You can turn it off by adding back the lint option in .flowconfig
:
# .flowconfig
[lints]
deprecated-utility=off
But it's actually not that hard to fix.
So what were $Subtype
and $Supertype
anyway? $Subtype
normally means what is expected here is more refined than what's inside $Subtype
. Anyway, that's just my understanding. You can still find the docs here.
Perhaps you previously used $Subtype
to refine component props, as suggested at the time of their deprecation, you can bring back the refinement using bounded generics.
Some older version of library definitions from Flow-Typed may raise errors. (For example, we were using Redux v3 before Flow 0.89 that caused unhappiness. However, there is already a libdef update in Flow-Typed.)
I felt a bit hairy about them anyway. Now that they're gone, time to feel happy and get rid of them :)
Changes and fixes around read-only object and array
Possible errors:
- Cannot assign
42
tox[0]
because read-only arrays cannot be written to. - Cannot assign
array
toproblem
because read-only array type [1] is incompatible with array type [2]. - Cannot assign
3
tox.a
because propertya
is not writable.
It's great to see that Flow is constantly improving and how. (Plus with a slight hint of humor to read about the fixes on the previous unsoundedness).
So I've found three changes and fixes around read-only things.
- Read-only arrays cannot be written to with any-typed indexes, commit
This now disallows you to mutate read only arrays. And you may ask, why should I be allowed to mutate them anyway? Turns out previously if the index is of type any
you would have been able to. 🤷🏻♀️
Then there are two more:
- Mixed refines to read-only object under typeof = object, commit
- Mixed refined by array produces $ReadOnlyArray, commit
I do not have a better explanation than the commit messages there. So let me quote:
[Bugbash] Mixed refines to read-only object under typeof = object
Summary:
It is not safe to refine mixed
to {[string] : mixed}
because this allows writes of any kind into the refined object, and we don't know what type of values the object holds. The only safe operation is to read mixed
out of the object, so the properties must be read only.
function bad (x : mixed) {
if (typeof x === "object" && x !== null) {
x.a = 3;
}
}
let obj : {a : string} = {a : "oops"};
bad(obj); // yikes
And the one with arrays:
[Bugbash] mixed refined by array produces $ReadOnlyArray<mixed>
Summary:
It is not safe to refine mixed
to Array<mixed>
as this allows for writing arbitrary values to the result of the refinement, and since we only know that the value is an array, we cannot know that it is safe to write a given value to the array. We do know, however, that anything we get out of the array will be mixed
, so it is safe to type it as a $ReadOnlyArray<mixed>
.
function bad(array: mixed) {
if (Array.isArray(array)) {
const problem: Array<mixed> = array; problem[1] = 0;
}
}
bad((["3"] : Array<string>));
Infer void before type checking starts for functions without a return statement
Possible errors:
Note: I think the possible errors caused by this fix can be quite variable. Here are two I know of:
- Cannot cast
x.noReturn()
to number because undefined [1] is incompatible with number [2]. - Cannot shadow proto property
yourFunction
[1] because object type [2] is incompatible with undefined [3] in the return value.
Commit on Flow codebase: Infer void early for functions with no explicit return
If a function does not have a return statement, Flow now infers that to void
. Interestingly, the most common errors that arise after this were regarding shadowing proto property. Check out the following Try Flow:
import * as React from 'react';
class MyComponent extends React.Component<*> {
handleClick: () => {}; // <- {} means an object here
handleClick() {
console.log('clicked!');
}
render() {
return <div onClick={this.handleClick} />
}
}
Fixes are simply to annotate them properly () => void
Fix a bug which prevented Flow from asking for required type annotations.
This line sounds scary 😱 But I haven't encountered any unhappiness that seems related yet. Will come back here if I do.
Top comments (3)
Thanks for this one :D I think this should be
deprecated-utility=off
though instead ofdeprecated-utility=false
.Hey hally9k thank you for pointing that out! Fixing now
shadowing proto property was a breaking change introduced in 0.81, and now it got stricter