& bringing types to our JavaScript
Engineer @ CA Agile Central
etc., etc., etc.
Object is not an Immutable.Map
Immutable.Map is not an Object
Creates a dependency graph of your modules.
Runs the modules' interactions through a rules engine.
Screams loudly if you break the rules.
No more spilled cheetos.
Screams loudly when we pass the wrong thing to a function.
Know the shape of the payload an action expects.
No bugs ever again (LOL). But seriously, no more "cannot read property foo of null".
cd path/to/your/project
npm install --save-dev flow-bin babel-transform-flow-strip-types
touch .flowconfig
# add // @flow to a file, any file
./node_modules/.bin/flow
// @flow
function doABarrelRoll(barrelName: string, timesToRoll: number): string {
return `${barrelName} is doing a barrel role ${timesToRoll} times`;
}
doABarrelRoll({ name: 'Stan' }, 'hi');
flow_test.js:6
6: doABarrelRoll({ name: 'Stan' }, 'hi');
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function call
6: doABarrelRoll({ name: 'Stan' }, 'hi');
^^^^^^^^^^^^^^^^ object literal. This type is incompatible with
2: function doABarrelRoll(barrelName: string, timesToRoll: number): string {
^^^^^^ string
flow_test.js:6
6: doABarrelRoll({ name: 'Stan' }, 'hi');
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function call
6: doABarrelRoll({ name: 'Stan' }, 'hi');
^^^^ string. This type is incompatible with
2: function doABarrelRoll(barrelName: string, timesToRoll: number): string {
^^^^^^ number
Get for free when you import immutable.
import { List, Map } from 'immutable';
export const listToArray = (list: List): array => list.toJS();
export const mapToObject = (map: Map): object => map.toJS();
// @flow
import { Map } from 'immutable';
type UserStoryCreatedAction = {
type: string,
payload: Map
};
export function createdUserStory(userStory: Map): UserStoryCreatedAction {
return {
type: 'USER_STORY_CREATED',
payload: userStory
};
};
// @flow
import { createdUserStory } from './userActions';
var userStory = {
title: 'Create a user story',
estimate: 13
};
createdUserStory(userStory);
flow_test.js:9
9: createdUserStory(userStory);
^^^^^^^^^^^^^^^^^^^^^^^^^^^ function call
9: createdUserStory(userStory);
^^^^^^^^^ object literal. This type is incompatible with
7: export function createdUserStory(userStory: Map): UserStoryCreatedAction {
^^^ Map. See: userActions.js:7
// @flow
function doABarrelRoll(barrelName: string, timesToRoll: number): ?Object {
return { name: barrelName, roll: timesToRoll };
}
function ultraBarrelRoll(): string {
var barrelRoll = doABarrelRoll('Stan', 3);
return `${barrelRoll.name} is now doing ${barrelRoll.roll} ultra barrel rolls`;
}
ultraBarrelRoll();
flow_test.js:9
9: return `Ultra ${barrelRoll.name} is now doing ${barrelRoll.roll} barrel rolls`;
^^^^ property `name`. Property cannot be accessed
on possibly null value
9: return `Ultra ${barrelRoll.name} is now doing ${barrelRoll.roll} barrel rolls`;
^^^^^^^^^^ null
flow_test.js:9
9: return `Ultra ${barrelRoll.name} is now doing ${barrelRoll.roll} barrel rolls`;
^^^^ property `roll`.
Property cannot be accessed on possibly null value
9: return `Ultra ${barrelRoll.name} is now doing ${barrelRoll.roll} barrel rolls`;
^^^^^^^^^^ null
<PROJECT_ROOT>/flow-typed
[libs] in .flowconfig
Declaration file next to implementation file (why Immtuable types are free)
Project Root
actions
UserStoryActions.js
UserStoryActions.js.flow
type UserStoryCreatedAction = {
type: string,
payload: Map
};
aka Ignore a lot of your node_modules
Specify a specific version of flow
[version]
0.27.0
Run analysis on code external to your project
Don't analyze these files. Useful for excluding problems that live in dependencies.
[ignore]
# Malformed json in `test/pkg-bower-json-malformed/bower.json:2`
.*/node_modules/bower-json/.*
# Malformed json in `test/broken.json:11`
.*/node_modules/config-chain/.*
# Malformed json in `test/fixtures/node_modules/invalidPackageJson/package.json: 1`
.*/node_modules/enhanced-resolve/.*
Tell flow where your custom types live. As of flow 0.24.0, it will check for custom types in <PROJECT_ROOT>/flow-typed.
A lot you can do here. tldr; Enable certain es2015+ features.
[options]
# Ignore flow warnings about not supporting decorator types
esproposal.decorators=ignore
# Ignore flow warnings about not support static fields
esproposal.class_static_fields=ignore
# Ignore flow warnings about not supporting instance fields
esproposal.class_instance_fields=ignore
npm install -g flow-bin
apm install nuclide
// package.json
"scripts": {
...
"flow": "./node_modules/.bin/flow"
...
}
Speed has been inconsistent. Nuclide can be a pain.
@thewillbeard