Neat features of Flow.

I recently took a couple hours to read through the Flow docs, which was an informative and valuable use of time. Here are a bunch of notes on useful and slightly intuitive aspects of Flow. Many of these code blocks are pulled from the docs.

Setting up Flow.

The Flow official page has decent installation instructions. If you're using Webpack and it's already working with Babel, all you need is to install the packages and edit your .babelrc file as they mention.

Setting up with Webstorm / Rubymine

This article provides a thorough explanation, but here's the basic takeaway:

  1. Go to Preferences | Languages & Frameworks | JavaScript in WebStorm and set language version to Flow.
  2. Specify the Flow executable to something similar to this path, replacing /path/to with your directory structure: /path/to/TransparentClassroom/node_modules/flow-bin/vendor/flow

Using Flow.

This page is a good place to get the basic understanding what what's going on, and then read here for all the information on different types, and it's good to start at the beginning and read through, it has a good linear progression. Most of them are pretty obvious or easy to find in the documentation (e.g. arrays, objects, functions). Here are a few that are less obvious, but very useful:

Union type

Allows you to specify more than one possible type.

function stringifyBasicValue(value: string | number | boolean) {  
  return '' + value;
}

Can also be written with leading vertical bar:

type Foo =  
  | Type1
  | Type2

Read-only properties

You can make properties of an object read-only, which can be super useful in helping enforce immutability. More here.

type Foo = { +bar: string }  
const a: Foo = { bar: 'hello' }  
a.bar = 'new' // Error: Flow: object type. Covariant property `bar` incompatible with contravariant use in assignment of property `bar`  

Disjoint union

Useful for when you know that the type will have certain properties dependent on a specific property, e.g. whether a server call was successful. Read more.

// @flow
type Success = { success: true, value: boolean };  
type Failed  = { success: false, error: string };

type Response = Success | Failed;

function handleResponse(response: Response) {  
  if (response.success) {
    var value: boolean = response.value; // Works!
  } else {
    var error: string = response.error; // Works!
  }
}

Mixed type

When the type is unknown.

function getTypeOf(value: mixed): string {  
  return typeof value;
}

Important! Don't confuse with any, which effectively disables type checking and can leak to other parts of the system.

$Keys

Useful for enums with values you want to access at runtime. More here.

// @flow
const countries = {  
  US: "United States",
  IT: "Italy",
  FR: "France"
};

type Country = $Keys<typeof countries>;

const italy: Country = 'IT';  
const nope: Country = 'nope'; // 'nope' is not a Country  

Maybe types vs. optional parameters

A maybe type is that type, undefined, or null. It's a ? in front of the type, e.g. ?number

// @flow
function acceptsMaybeNumber(value: ?number) {  
  // ...
}

acceptsMaybeNumber(42);        // Works!  
acceptsMaybeNumber();          // Works!  
acceptsMaybeNumber(undefined); // Works!  
acceptsMaybeNumber(null);      // Works!  
acceptsMaybeNumber("42");      // Error!  

An optional parameter is specified with a ? after the variable name. It means the parameter is either specified or undefined, but not null.

// @flow
function acceptsObject(value: { optionalProp?: string }) {  
  // ...
}

acceptsObject({ foo: "bar" });     // Works!  
acceptsObject({ foo: undefined }); // Works!  
// $ExpectError
acceptsObject({ foo: null });      // Error!  
acceptsObject({});                 // Works!  

Using Flow with Redux.

The Redux GitHub repo has a nice starter example of using Flow with Redux. Noteworthy points:

  • Defining types in a separate folder, and using them everywhere for consistency
  • Making Actions and other state variables read-only through the use of covariant properties
  • Using same properties that define state as properties on React components. Now it's much easier to keep React component types in sync with state. Whoo!

Digging deeper.

There's much more to explore, and this page offers a good starting point. Happy digging.