1

I'm currently in the process of comparing the Google Closure Compiler and the Flow static type checker, in terms of expressiveness. What I like about the latter is that it apparently can represent tagged unions quite nicely. The manual gives this example:

type Result = Done | Error; // a disjoint union type with two cases
type Done = { status: 'done', answer: Matrix };
type Error = { status: 'error', message: string };

Is there a way to do something like this using Closure Compiler? That means some way to force certain proprties of an object to not only be of a specific type, but have a fixed value? And to use that value for type inference, to distinguish between different options in a union? I found no documentation to this effect.

MvG
  • 57,380
  • 22
  • 148
  • 276

1 Answers1

2

There isn't an exact translation. Here's how I would write this:

/** @enum {string} */
var ResultStatus = {
  DONE: 'done',
  ERROR: 'error'
};

/** @record */
var Done = function() {};

/** @type {ResultStatus} */
Done.prototype.status;

/** @type {Matrix} */
Done.prototype.answer;

/** @record */
var Error = function() {};

/** @type {ResultStatus} */
Error.prototype.status;

/** @type {string} */
Error.prototype.message;

/** @type {Result|Error} */
var Result;

This is a very verbose syntax but provides the best type checking. Any object with those properties is assumed to match the type. Extra properties are allowed.

There's a much shorter syntax with slightly different behavior: typedefs.

/** @enum {string} */
var ResultStatus = {
  DONE: 'done',
  ERROR: 'error'
};

/**
 * @typedef{{
 *   status: ResultStatus
 *   answer: Matrix
 * }}
 */
var Done;

/**
 * @typedef{{
 *   status: ResultStatus
 *   message: string
 * }}
 */
var Error;

/** @type {Result|Error} */
var Result;

There are several other ways to write these types as well. Which you choose depends on what you want checked. For instance, do you want a warning if you misspell (or try to add) a property? Do you want an exact match on both property names or types, or are extra properties allowed?

Chad Killingsworth
  • 14,360
  • 2
  • 34
  • 57
  • Didn't know one could use an `enum` as a type. If I undertand you correctly, both the forms you suggest say that the `status` property can be either of the two values, without fixing the link between value and corresponding type. Perhaps one single-element `enum` per type would serve that purpose… Will have to experiment a bit with that. – MvG Dec 17 '16 at 18:10