Calculate all possible combinations of an array of arrays or strings
You don't need the else if/else blocks at the top; it can just be if blocks, since they return and thus exit the function anyway.

if (arr.length === 0) {
  return []; // stop here
} 

if (arr.length === 1){
  return arr[0]; // or here
}

// or continue with the rest of the function

As you yourself noted, normalize the input, so you don't need to be type-checking inside the loop


But I'd advice you ignore that you're dealing with strings specifically, and just worry about "combinations of stuff", and try for a generic solution.

Still, the manual array-building makes your code cryptic. I'd suggest a more functional approach, using map and reduce.

Not saying it's easier to follow at first glance, but there's less code, and it's generic:

// this produces a 2d array of combinations
function combinations(array) {
  if(!array.length) {
    return [];
  }

  // wrap non-array values
  // e.g. ['x',['y','z']] becomes [['x'],['y','z']]
  array = array.map(function (item) {
    return item instanceof Array ? item : [item];
  });

  // internal recursive function
  function combine(list) {
    var prefixes, combinations;

    if(list.length === 1) {
      return list[0];
    }

    prefixes = list[0];
    combinations = combine(list.slice(1)); // recurse

    // produce a flat list of each of the current
    // set of values prepended to each combination
    // of the remaining sets.
    return prefixes.reduce(function (memo, prefix) {
      return memo.concat(combinations.map(function (combination) {
        return [prefix].concat(combination);
      }));
    }, []);
  }

  return combine(array);
}


To convert the output of the above function to strings, just add another map call:

function allPossibleCases(arr) {
  return combinations(arr).map(function (combination) {
    return combination.join(" ");
  });
}


You get this:

[ 'x', 'y', 'z' ]                   =&gt; [ 'x y z' ]
[ [ 'a', 'b' ], 'c', 'd' ]          =&gt; [ 'a c d', 'b c d' ]
[ [ 'a', 'b' ], [ 'c', 'd' ], 'e' ] =&gt; [ 'a c e', 'a d e', 'b c e', 'b d e' ]


Note that the order of the last one is different from yours, though it contains the same combinations.