1
\$\begingroup\$

The function checks whether an array is of a specific type (only contains elements of that type), the types the function accepts for checking is basically all the JavaScript types plus any types that the user may define manually (using a constructor).

What would you do to make the function more sophisticated? What would you remove or add? How would you improve or extend the function?

const checkArrayType = function checkArrayType(arr, type) {
  
  if (!Array.isArray(arr)) {
    throw new Error('The argument "arr" must be an array!');
  }
  else if (type !== null && type !== undefined && typeof type != 'function') {
    throw new Error('The argument "type" must be a function, "null", or "undefined"!');
  }
  
  // 'null' and 'undefined' require a different check than the main one
  if (type === null || type === undefined) {
    return arr.every(function(e){
      return e === type;
    });
  }
  
  return arr.every(function(e){
    /* 
     * not using 'instanceof' because it would return 'true'
     * for cases like 'subObj instanceof Object'. 
     * ---------------------------------
     * using 'Object(e)' so that the check works for primitives, see:
     * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object
     */
    return Object.getPrototypeOf(Object(e)) === type.prototype;
  });
  
};


console.log(checkArrayType([1,2,3,4], Number)); // true
console.log(checkArrayType(['hello', 10], String)); // false
console.log(checkArrayType([[1, 2.5], ['a', 'b']], Array)); // true
console.log(checkArrayType([null, null, null, null], null)); // true
console.log(checkArrayType([new String('hello'), new String('world')], Object)); // false

var Foo = function Foo(){};
console.log(checkArrayType([new Foo(), new Foo()], Foo)); // true

console.log(checkArrayType({a: null}, null)); // throws error
console.log(checkArrayType([], 'abc')); // throws error

One more thing, how am I supposed to deal with long comments like the one in this snippet ?

\$\endgroup\$
  • 1
    \$\begingroup\$ Maybe an optional parameter that if true will check if an item can be cast to the given type. For example, "1234" isn't a number, but could be cast to one without an error. \$\endgroup\$ – Ctznkane525 Jan 2 '18 at 0:56
  • 2
    \$\begingroup\$ I have rolled back the last edit. Please see What to do when someone answers. \$\endgroup\$ – Martin R Jan 2 '18 at 8:57
3
\$\begingroup\$

The implementation could be written more compactly using arrow functions, for example:

if (type === null || type === undefined) {
  return arr.every(e => e === type);
}

return arr.every(e => Object.getPrototypeOf(Object(e)) === type.prototype);

There are two arr.every calls at different execution paths. You could eliminate that duplicated logic by extracting the function parameter of arr.every to a variable:

var checker;
if (type === null || type === undefined) {
  checker = e => e === type;
} else {
  checker = e => Object.getPrototypeOf(Object(e)) === type.prototype;
}

return arr.every(checker);
\$\endgroup\$
  • \$\begingroup\$ Thanks for answering! Why arrow functions if you are not using this though ? \$\endgroup\$ – doubleOrt Jan 2 '18 at 8:38
  • 1
    \$\begingroup\$ @Taurus arrow functions are especially appropriate when you're not using this. They are best with pure functions with no state. \$\endgroup\$ – janos Jan 2 '18 at 8:45
  • \$\begingroup\$ A bit of a general question, don't you think !== is more straightforward and readable than === ? I don't know but to my brain it seems that way. \$\endgroup\$ – doubleOrt Jan 2 '18 at 8:54
  • 1
    \$\begingroup\$ @Taurus I've never felt readability issues with these operators. But depending on the conditions used, there are sometimes readability aspects when choosing between some complex condition and its negated version, applying DeMorgan's Law, and arranging if and else statements. \$\endgroup\$ – janos Jan 2 '18 at 9:09
1
\$\begingroup\$

The function does one thing well. I would change nothing. Wait for your calling code to develop a need for fancier functionality, and develop a (related) fancier function then.

The console.log() calls, with comments suggesting true return is expected, would benefit from being placed within a unit test framework.

You asked about the long comment. Delete the "----" ascii art. Prefer full sentences to sentence fragments. And for http://very-very-very-long.com/urls consider introducing them with a bit.ly shortened URL. Then there's something for a person to copy-n-paste / click on, and verify they landed in the expected place, while also giving you the flexibility to line wrap it, and defending against link rot as the months go by.

\$\endgroup\$
  • \$\begingroup\$ I thought that was an actual website for a while. How do they protect from link rot though ? \$\endgroup\$ – doubleOrt Jan 1 '18 at 21:00
  • 1
    \$\begingroup\$ Link rot is a fact of life; pages (and sites) go 404 all the time. Half-life is on the order of eight months, with some folks (like NYTimes) being much better at URL-naming and archival storage than other folks. It is the responsibility of a comment's author to protect against link rot, by offering full citation, giving short (convenient, clickable) URL plus full (line wrapped) URL. The trouble with offering just a shortened URL is the target site might delete the page and 301 to another page, rather than correctly 404'ing the deleted page. Your 87-character URL can be hard to linewrap nicely. \$\endgroup\$ – J_H Jan 1 '18 at 21:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.