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);
}
}