Skip to content

Instantly share code, notes, and snippets.

@uniphil
Created September 22, 2015 12:18
Show Gist options
  • Save uniphil/a36ebe626c7b949c3888 to your computer and use it in GitHub Desktop.
Save uniphil/a36ebe626c7b949c3888 to your computer and use it in GitHub Desktop.
results runtime typechecks

Idea: let the enum declare how many arguments each EnumOption takes

const ProjectActions = Enum({
  CLEAR: 0,
  SELECT: 1,
  HOVER: 1,
  RENAME: 2,
});
  • WIN ERGONOMIC: declarative source-code documentation of the options' arg count
  • Mutually exclusively, either: - WIN PERFORMANCE: create fast factories for 0- and 1-arg options - LOSE DEBUGGING: truncating args for 0- and 1-arg calls
    • OR
      • LOSE PERFORMANCE: validate the number of args passed to the option
      • WIN DEBUGGING: helpful errors when options get the wrong num of args
  • LOSE SURPRISE: None of the above would be obvious behaviour from looking at Enum user code.

The surprising behaviour kills this idea, I think.

Idea: let the enum provide an array of typeof strings for each option

const ProjectActions = Enum({
  CLEAR: [],
  SELECT: ['number'],
  HOVER: ['number'],
  RENAME: ['number', 'string'],
});
  • WIN ERGONOMIC: declarative source-code documentation of the options' arg count and type-ish
  • WIN DEBUGGING: arg-count and arg-type help in error messages.
  • LOSE FLEXIBILITY:
    • typeof is terrible: typeof null === typeof [] === typeof new String('') == 'object'
    • No catch-all possible. Special 'any' string or similar is super-ugly.

Small wins that don't go far enough and actually limit functionality.

Idea: let the enum provide classes for instanceOf checks for each option

const ProjectActions = Enum({
  CLEAR: [],
  SELECT: [/*haha javascript hates me there is no valid class for a number literal*/],
  HOVER: [/*la la la la*/],
  RENAME: [/*Nothing for number literal*/,/*also nothing for string literal lol*/],
})

nope.

Idea: let the enum provide an array of validation functions for each option

const ProjectActions = Enum({
  CLEAR: [],
  SELECT: [id => typeof id === 'number'],  // inline validator fn
  HOVER: [_.isNumber],  // or any existing validator fn
  RENAME: [_.isNumber, (newName => _.isString(newName) && newName.length > 2)],
});
  • WIN ERGONOMIC: declarative source-code documentation of the arg counts and type validation
  • WIN DEBUGGING: arg-count and which-arg-failed help in error messages.

The user code for this seems to suggest the right things, to me. I kinda like this one.

Idea: let the enum provide config objects to make anything possible.

const ProjectActions = Enum({
  CLEAR: {argCount: 0},
  SELECT: {args: [
    {validate: _.isNumber},
  ]},
  HOVER: {argCount: 1, check: false},  // fast-constructor
  RENAME: {args: [
    {validate: _.isNumber},
    {validate: newName => _.isString(newName) && newName.length > 2},
  ]},
});

...or any other of the infinite ways you could imagine to configure argument validation...

Idea: maybe this is all something to fix with typescript instead. :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment