Checking the types of function arguments in Javascript

In Javascript, is there any way to check the types of a function's arguments? I want to write a function called checkTypes that does the following:

function checkTypes(typeArr){
    //if the types do not match typeArr, throw an error
}

function exampleUsage(arr1, arr2, num1){
    checkTypes("object", "object", "number");
    //throw an error if the types do not match the corresponding elements
}

Answers:

Answer

You can use the the typeOf function adapted from this post Fixing the JavaScript typeof operator combined with this function:

function typeOf( obj ) {
  return ({}).toString.call( obj ).match(/\s(\w+)/)[1].toLowerCase();
}

function checkTypes( args, types ) {
  args = [].slice.call( args );
  for ( var i = 0; i < types.length; ++i ) {
    if ( typeOf( args[i] ) != types[i] ) {
      throw new TypeError( 'param '+ i +' must be of type '+ types[i] );
    }
  }
}

function foo( a,b,c ) {
  checkTypes( arguments, ['string', 'number', 'array'] );
  return 'foo';
}

console.log( foo( 'a', 1, [2] ) ); //=> foo
console.log( foo( 1, 1, [2] ) ); 
//^ Uncaught TypeError: param 0 must be of type string
Answer

Do not use typeof in this case. It's problematic for several reasons:

typeof null                 // 'object'
typeof []                   // 'object'
typeof 'foo'                // 'string'
typeof new String('foo')    // 'object'
'foo' == new String('foo')  // true

Instead, use Object::toString:

Object.prototype.toString.call(null)               // '[object Null]'
Object.prototype.toString.call([])                 // '[object Array]'
Object.prototype.toString.call('foo')              // '[object String]'
Object.prototype.toString.call(new String('foo'))  // '[object String]'

A decorator would meet your requirements:

var getType = function(value) {
  return Object.prototype.toString.call(value)
    .replace(/^\[object |\]$/g, '').toLowerCase();
};

var checkTypes = function(types, fn) {
  return function() {
    var args = Array.prototype.slice.call(arguments, 0);
    for (var idx = 0; idx < types.length; idx += 1) {
      var expected = types[idx];
      var received = getType(args[idx]);
      if (received != expected) {
        throw new TypeError('expected ' + expected + '; received ' + received);
      }
    }
    fn.apply(null, args);
  };
};

var exampleUsage = checkTypes(['array', 'array', 'number'], function(arr1, arr2, num1) {
  console.log('arr1:', arr1);
  console.log('arr2:', arr2);
  console.log('num1:', num1);
});

Usage examples:

exampleUsage([], [], 0);
// arr1: []
// arr2: []
// num1: 0

exampleUsage([], [], 'foo');
// TypeError: expected number; received string
Answer

You can use a modified version of typeof and the arguments pseudo-array to get each argument type and compare it to your desired set of types:

// from Doug Crockford http://javascript.crockford.com/remedial.html
function typeOf(value) {
    var s = typeof value;
    if (s === 'object') {
        if (value) {
            if (Object.prototype.toString.call(value) == '[object Array]') {
                s = 'array';
            }
        } else {
            s = 'null';
        }
    }
    return s;
}

function checkTypes(argList, typeList) {
    for (var i = 0; i < typeList.length; i++) {
        if (typeOf(argList[i]) !== typeList[i]) {
            throw 'wrong type: expecting ' + typeList[i] + ", found " + typeOf(argList[i]);
        }
    }
}

Working demo: http://jsfiddle.net/jfriend00/ywyLe/


Example Usage:

function exampleUsage(arr1, arr2, num1){
    //throw an error if the types do not match the corresponding elements
    checkTypes(arguments, ["array", "array", "number"]);
}
Answer

You are looking for typeof operator.

Answer

The typeof function return object for most of the thing,

alert(typeof("this is string")); /* string */
alert(typeof(1234)); /* number */
alert(typeof([])); /* object */
alert(typeof({})); /* object */
alert(typeof(new Date)); /* object */
alert(typeof(function(){})); /* function */

but jQuery can identify by this function jQuery.type( obj ) http://api.jquery.com/jQuery.type/

Answer

If anyone is looking for require-like environment solution, I can recommend typeof-arguments package.

const checkTypes = require('typeof-arguments');

function exampleUsage(arr1, arr2, num1){
  checkTypes(arguments,["object", "object", "number"]);
  //throw an error if the types do not match the corresponding elements
}
Answer

JavaScript is bad for types. Also, you can not magically access the parent's function arguments from a calling function.

If you don't want to have a big headache, use some simple library to check types.

For example, using underscore.js you could write something like this:

function exampleUsage(arr1, arr2, num1) {
  if(!_.isArray(arr1) || !_.isArray(arr2) || !_.isNumber(num1) {
    throw "Wrong types"
  }
  // do other stuff
}

You are probably afraid of types because you are probably new to dynamic languages. You will see that is not as bad as it looks like, but JavaScrip IS BAD (for a lot other reasons)

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.