Skip to content
Norman Rzepka edited this page Jun 12, 2017 · 6 revisions

Flow is a static typechecker for JavaScript, which can catch a lot of common bugs before the code is run. It relies on type annotations, but can also infer a lot of type information, which reduces verbosity.

How to run Flow

You can simply run npm run flow which performs a full re-check of the entire project. However, it's more efficient to run flow directly from the command line which spawns a server in the background. This server listens to all file modifications and automatically checks incrementally. All subsequent flow executions will typically be very fast.

If you wish to stop the flow server you can call flow stop.

How to add type annotations

Weak type checking

Since webknossos' JavaScript base was started without any type annotations, we have to incrementally add annotations to the code. The easiest way to make flow check a file is to add a special header to it:

/**
 * file_name.js
 * @flow weak
 */

Afterwards, flow will weakly typecheck this file. This means that it only complains if it is pretty certain about a type error. If it can't infer type information, it will assume any as a type which allows practically everything. However, it will complain for example about writing and reading instance variables of a class, if these were not declared. Such declarations can look like this:

import SomeClass from '...'
import type { SomeType } from '...';

export type Vector = [number, number, number];

class ClassName {
  aString: string;
  aNumber: number;
  aBoolean: boolean;
  aSomeType: SomeType;
  aParameterlessFunctionWhichReturnsAString: () => string;
  aVector: Vector:
  aSomeClassInstance: SomeClass;
}

Strong type checking

If a file is already weakly typechecked, we can make the typechecking strong by omitting the weak keyword in the header like this:

/**
 * file_name.js
 * @flow
 */

Afterwards, flow will additionally demand type declarations for all parameters and return values of all functions. Example:

class SomeClass {
  aMethod(aBoolean: boolean): string {
    return aBoolean ? "yes" : "no";
  }

  // A new type can be constructed by composing two types with | or & (meaning union or intersection).
  // Putting a ? in front of a type means, that this type is nullable (i.e., ?aType is equal to aType | null).
  anotherMethod(aString: string): number | ?string {
    if (aString === "number") {
      return 3;
    } else if (aString === "string") {
      return "3";
    } else {
      return null;
    }
  }
}

Documentation

For a very good overview about Flow, have a look at the documentation. Also check out the live editor with immediate flow checks.

Flow coverage

If you want to get a detailed report about the current flow coverage you can run npm run flow-coverage. This will output a report on the command line as well as a html file in a folder called flow-coverage.

Clone this wiki locally