-
Notifications
You must be signed in to change notification settings - Fork 29
Flow
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.
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
.
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;
}
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;
}
}
}
For a very good overview about Flow, have a look at the documentation. Also check out the live editor with immediate flow checks.
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
.