Updated 2016-08-19 (originally posted ) — Flow — 4 min read
From the announcement post:
Path-sensitive analysis means that Flow reads control flow to narrow types where appropriate.
This example comes from the announcement post:
The presence of a use of
length with a
null argument informs Flow that there
should be a null check in that function.
This version does type-check:
Flow is able to infer that
x cannot be
null inside the
An alternate fix would be to get rid of any invocations of
length where the
argument might be
That would cause Flow to infer a non-nullable type for
This capability goes further - here is an example from the Flow documentation:
The type of
o is initially
But Flow is able to determine that the type of
o changes when
and that its type is definitely
string on the last line.
In addition to null checks, Flow also narrows types when it sees dynamic type checks. This example (which passes the type checker) comes from the documentation:
The inferred return type of
string | number.
That is a type union,
meaning that values returned by
foo might be of type
string or of type
typeof checks in
bar narrow the possible types of
y in the
if body to just
That means that it is safe to multiply values returned by
the type checker knows that
bar will always return a number.
A coworker told me that what he would like is support for type-checked structs. That would let him add or remove properties from an object in one part of a program, and be assured that the rest of the program is using the new object format correctly. Struct types work using structural types and type aliases:
type keyword and type annotation on
Facebook's literature is a little misleading,
syntax for type aliases and type annotations,
and the type-checking step.
These are early days for Flow. I am optimistic that over time it will only get better at operating on code that was not written with Flow in mind.
Edit 2016-08-19: Early in Flow's development, Facebook recommended using their own jsx compiler to process code that used Flow. That is what produced ECMAScript 5 code, as mentioned in the previous paragraph. Currently the best practice is to use Babel with the React preset to process Flow code. You still get the benefit of transpiling ECMAScript 6 code to ECMAScript 5, if you have Babel configured to do that.
One of my favorite features of Flow is that
undefined are not
treated as bottom types.
A value is only allowed to be
null if it has a nullable type.
This makes Flow better at catching null pointer exceptions than almost any other
A type expression
?T behaves pretty much like
T | null | undefined.
(From what I can tell,
undefined are distinct types in Flow -
but it does not seem to be possible to use them in type annotations at this
void is allowed, which seems to be an alias for
Thanks to type narrowing, accessing
tree.value passes type-checking in the
if body where
tree instanceof Node is true.
Without that check, the type checker would not allow accessing properties that
do not exist on both
There are some details in this example that I want to call out:
classsyntax is from ECMAScript 6 - but it is extended in Flow to support type annotations for properties.
Treeis a type alias. It has no runtime representation. None is needed, since
EmptyTreehave no shared behavior. And unlike a superclass,
Treeis sealed, meaning that it is not possible to add more subtypes to
Treeelsewhere in the codebase.
- Flow supports parameterized types (a.k.a. generics, a.k.a. parametric polymorphism).
- You can specify the exact type of function values (in this case, the type of
findmight return a value from a tree, or it might return
undefined. So the return type is
T | void(where
voidis the type of
?Twould also work.