Skip to main content

Version-0.14.0

It has come to our attention that not everyone obsessively checks GitHub for Flow releases. This came as a surprise, but we would like to support these users too. Therefore, we will start announcing each Flow release on the blog, starting with this release.

So here is Flow v0.14.0! Check out the Changelog for the canonical list of what has changed.

Announcing Disjoint Unions

Sometimes programs need to deal with different kinds of data all at once, where the shape of the data can be different based on what kind of data the code is looking at. This kind of programming is so common in functional programming languages that almost all such languages come with a way of:

  • Specifying such data by a set of disjoint cases, distinguished by “tags”, where each tag is associated with a different “record” of properties. (These descriptions are called “disjoint union” or “variant” types.)
  • Doing case analysis on such data, by checking tags and then directly accessing the associated record of properties. (The common way to do such case analysis is by pattern matching.)

Examples of programs that analyze or transform such data range from compilers working with abstract syntax trees, to operations that may return exceptional values, with much more in between!

As of Flow 0.13.1 it is now possible to program in this style in JavaScript in a type-safe manner. You can define a disjoint union of object types and do case analysis on objects of that type by switching on the value of some common property (called a "sentinel") in those object types.

Flow's syntax for disjoint unions looks like:

type BinaryTree =
{ kind: "leaf", value: number } |
{ kind: "branch", left: BinaryTree, right: BinaryTree }

function sumLeaves(tree: BinaryTree): number {
if (tree.kind === "leaf") {
return tree.value;
} else {
return sumLeaves(tree.left) + sumLeaves(tree.right);
}
}

Announcing Bounded Polymorphism

As of Flow 0.5.0, you can define polymorphic functions and classes with bounds on their type parameters. This is extremely useful for writing functions and classes that need some constraints on their type parameters. Flow's bounded polymorphism syntax looks like

class BagOfBones<T: Bone> { ... }
function eat<T: Food>(meal: T): Indigestion<T> { ... }

The problem

Consider the following code that defines a polymorphic function in Flow:

function fooBad<T>(obj: T): T {
console.log(Math.abs(obj.x));
return obj;
}

This code does not (and should not!) type check. Not all values obj: T have a property x, let alone a property x that is a number, given the additional requirement imposed by Math.abs().

Announcing Flow Comments

As of Flow 0.4.0, you can put your Flow-specific syntax in special comments. If you use these special comments then you do not need to transform away Flow-specific syntax before running your code. While we strongly recommend that you write your code without the special comments, this feature will help people who can't fit a Flow-stripping transformation into their setup. This was one of our most requested features and hopefully it will enable even more people to use Flow!

This feature introduces 3 special comments: /*:, /*::, and /*flow-include. Flow will read the code inside these special comments and treat the code as if the special comment tokens didn't exist. These special comments are valid JavaScript block comments, so your JavaScript engine will ignore the code inside the comments.

Announcing Import Type

As of Flow 0.3.0, it's now possible to import types from another module. So, for example, if you're only importing a class for purposes of referencing it in a type annotation, you can now use the new import type syntax to do this.

Motivation

Has this ever happened to you:

// @flow

// Post-transformation lint error: Unused variable 'URI'
import URI from "URI";

// But if you delete the require you get a Flow error:
// identifier URI - Unknown global name
module.exports = function(x: URI): URI {
return x;
}

Now you have an out! To solve this problem (and with an eye toward a near future with ES6 module syntax), we've added the new import type syntax. With import type, you can convey what you really mean here — that you want to import the type of the class and not really the class itself.

Announcing Typecasts

As of version 0.3.0, Flow supports typecast expression.

A typecast expression is a simple way to type-annotate any JavaScript expression. Here are some examples of typecasts:

(1 + 1 : number);
var a = { name: (null: ?string) };
([1, 'a', true]: Array<mixed>).map(fn);

For any JavaScript expression <expr> and any Flow type <type>, you can write

(<expr> : <type>)

Note: the parentheses are necessary.