index.js
function (args) {
   // Find the minimum expected length.
   var expected = Array.prototype.slice.call(arguments, 1);
   var minimum = expected.length
   var hasOptionalTypes = false;
   
   for (var i = 0; i < expected.length; i++) {
      if (!isValidType(expected[i])) {
         throw Error('Expected argument ' + i + ' is not a valid type.');
      }
      if (isOptionalType(expected[i])) {
         minimum--;
         hasOptionalTypes = true;
      }
   };
   // Exit early if in production, INSIST_IN_PROD is not equal to true and there are no optional
   // options.
   if (isDisabled && !hasOptionalTypes) {
      return [];
   }

   // Check if the args and expected lengths are different (and there are no optional args).
   if (minimum == expected.length && args.length != expected.length) {
      throw Error(getExpectedVsRecieved_(expected, args));
   }
   // Check if the args are within the expected range.
   if (args.length < minimum || args.length > expected.length) {
      throw Error(getExpectedVsRecieved_(expected, args));
   }

   // We don't have to worry about shifting if all the arguments are present.
   if (args.length === expected.length) {
      for (var i = 0; i < expected.length; i++) {
         if (!isOfType(args[i], expected[i])) {
            throw Error(getExpectedVsRecieved_(expected, args));
         }
      };
      return args;
   }

   return shiftArguments_(expected, args, minimum);
}
function (args) {
   // Find the minimum expected length.
   var expected = Array.prototype.slice.call(arguments, 1);
   var minimum = expected.length
   var hasOptionalTypes = false;
   
   for (var i = 0; i < expected.length; i++) {
      if (!isValidType(expected[i])) {
         throw Error('Expected argument ' + i + ' is not a valid type.');
      }
      if (isOptionalType(expected[i])) {
         minimum--;
         hasOptionalTypes = true;
      }
   };
   // Exit early if in production, INSIST_IN_PROD is not equal to true and there are no optional
   // options.
   if (isDisabled && !hasOptionalTypes) {
      return [];
   }

   // Check if the args and expected lengths are different (and there are no optional args).
   if (minimum == expected.length && args.length != expected.length) {
      throw Error(getExpectedVsRecieved_(expected, args));
   }
   // Check if the args are within the expected range.
   if (args.length < minimum || args.length > expected.length) {
      throw Error(getExpectedVsRecieved_(expected, args));
   }

   // We don't have to worry about shifting if all the arguments are present.
   if (args.length === expected.length) {
      for (var i = 0; i < expected.length; i++) {
         if (!isOfType(args[i], expected[i])) {
            throw Error(getExpectedVsRecieved_(expected, args));
         }
      };
      return args;
   }

   return shiftArguments_(expected, args, minimum);
}
Asserts that the arguments supplied are what's expected. If an argument can be multiples
types, use an array of acceptable types.
@param {Array.<?>} args
@param {?,..} expected types
@return Returns an array with the arguments shifted into the correct indices.