visitors.js
function visitTypedFunction(traverse, node, path, state) {
  var klass = getParentClassDeclaration(path);
  var generics = klass && klass.typeParameters ? toLookup(klass.typeParameters.params.map(getName)) : {};
  if (node.typeParameters) {
    generics = mixin(generics, toLookup(node.typeParameters.params.map(getName)));
  }
  var ctx = new Context(state, generics);
  var rest = node.rest ? ', ' + ctx.getType(node.rest.typeAnnotation.typeAnnotation) : '';
  var types = [];
  var params = [];
  node.params.forEach(function (param) {
    var type = ctx.getType(param.typeAnnotation ? param.typeAnnotation.typeAnnotation : null);
    types.push(param.optional ? ctx.getProperty('optional') + '(' + type + ')' : type);
    params.push(param.name);
  });

  utils.catchup(node.body.range[0] + 1, state);

  if (params.length || rest) {
    utils.append(ctx.getProperty('check') + '(arguments, ' + ctx.getProperty('arguments') + '([' + types.join(', ') + ']' + rest + '));', state);
  }

  if (node.returnType) {
    var returnType = ctx.getType(node.returnType.typeAnnotation);
    utils.append(' var ret = (function (' + params.join(', ') + ') {', state);
    traverse(node.body, path, state);
    utils.catchup(node.body.range[1] - 1, state);
    utils.append('}).apply(this, arguments); return ' + ctx.getProperty('check') + '(ret, ' + returnType + ');', state);
  } else {
    traverse(node.body, path, state);
  }

  return false;
}
function visitTypedFunction(traverse, node, path, state) {
  var klass = getParentClassDeclaration(path);
  var generics = klass && klass.typeParameters ? toLookup(klass.typeParameters.params.map(getName)) : {};
  if (node.typeParameters) {
    generics = mixin(generics, toLookup(node.typeParameters.params.map(getName)));
  }
  var ctx = new Context(state, generics);
  var rest = node.rest ? ', ' + ctx.getType(node.rest.typeAnnotation.typeAnnotation) : '';
  var types = [];
  var params = [];
  node.params.forEach(function (param) {
    var type = ctx.getType(param.typeAnnotation ? param.typeAnnotation.typeAnnotation : null);
    types.push(param.optional ? ctx.getProperty('optional') + '(' + type + ')' : type);
    params.push(param.name);
  });

  utils.catchup(node.body.range[0] + 1, state);

  if (params.length || rest) {
    utils.append(ctx.getProperty('check') + '(arguments, ' + ctx.getProperty('arguments') + '([' + types.join(', ') + ']' + rest + '));', state);
  }

  if (node.returnType) {
    var returnType = ctx.getType(node.returnType.typeAnnotation);
    utils.append(' var ret = (function (' + params.join(', ') + ') {', state);
    traverse(node.body, path, state);
    utils.catchup(node.body.range[1] - 1, state);
    utils.append('}).apply(this, arguments); return ' + ctx.getProperty('check') + '(ret, ' + returnType + ');', state);
  } else {
    traverse(node.body, path, state);
  }

  return false;
}
function visitTypedFunction ( traverse , node , path , state ) { var klass = getParentClassDeclaration ( path ) ; var generics = klass && klass . typeParameters ? toLookup ( klass . typeParameters . params . map ( getName ) ) : { } ; if ( node . typeParameters ) { generics = mixin ( generics , toLookup ( node . typeParameters . params . map ( getName ) ) ) ; } var ctx = new Context ( state , generics ) ; var rest = node . rest ? ', ' + ctx . getType ( node . rest . typeAnnotation . typeAnnotation ) : '' ; var types = [ ] ; var params = [ ] ; node . params . forEach ( function ( param ) { var type = ctx . getType ( param . typeAnnotation ? param . typeAnnotation . typeAnnotation : null ) ; types . push ( param . optional ? ctx . getProperty ( 'optional' ) + '(' + type + ')' : type ) ; params . push ( param . name ) ; } ) ; utils . catchup ( node . body . range [ 0 ] + 1 , state ) ; if ( params . length || rest ) { utils . append ( ctx . getProperty ( 'check' ) + '(arguments, ' + ctx . getProperty ( 'arguments' ) + '([' + types . join ( ', ' ) + ']' + rest + '));' , state ) ; } if ( node . returnType ) { var returnType = ctx . getType ( node . returnType . typeAnnotation ) ; utils . append ( ' var ret = (function (' + params . join ( ', ' ) + ') {' , state ) ; traverse ( node . body , path , state ) ; utils . catchup ( node . body . range [ 1 ] - 1 , state ) ; utils . append ( '}).apply(this, arguments); return ' + ctx . getProperty ( 'check' ) + '(ret, ' + returnType + ');' , state ) ; } else { traverse ( node . body , path , state ) ; } return false ; }
handle typed functions a typed function is a function such that at least one param or the return value is typed
handle typed functions a typed function is a function such that at least one param or the return value is typed