11

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
}
15
  • In order to get this to work properly, I'll need to find a way to get the array of arguments from inside a function. Commented Dec 18, 2012 at 4:23
  • 3
    You can access an arguments object with all the arguments and the number of arguments. It behaves much like an array (though it isn't one). Read this for more info: developer.mozilla.org/en-US/docs/JavaScript/Reference/… Commented Dec 18, 2012 at 4:28
  • 2
    the question you should be asking yourself is, why do you care what type the arguments are? Commented Dec 18, 2012 at 4:34
  • 2
    @AndersonGreen: Stop it. :P Javascript is not any of those many other languages. The whole concept of classes doesn't even exist natively; it's bolted on to appease people who can't wrap their heads around prototypes, and is so easy to subvert (even accidentally!) that relying on it for much of anything will drive you insane. Commented Dec 18, 2012 at 5:09
  • 1
    @AndersonGreen: myArray.constructor = Object;, for example. Or Array = function() {};. Depends on how you do your type check, but basically, no one way of checking is foolproof. You'd have to verify stuff a half dozen different ways, at which point you've spent more time on bureaucracy than actual work. Commented Dec 18, 2012 at 5:36

7 Answers 7

17

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
Sign up to request clarification or add additional context in comments.

6 Comments

Is there any way to obtain the arguments of the calling function in checkTypes (without passing in the arguments as a parameter)?
There must be a way but why you want to do this? You could use TypeScript for example if you need strong typing.
Here's a modified version of the code above (with the same output, but slightly more concise): jsfiddle.net/BpVBG
You should throw a TypeError here, not a string.
Doesn't {}.toString (or any property) give a syntax error?
|
10

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

Comments

3

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"]);
}

3 Comments

In checkTypes, is it possible to obtain the args list from the calling function, without explicitly passing it as a parameter? It would be more concise this way, if it were possible.
@AndersonGreen - Obtaining arguments of a calling function is not possible in a cross-browser fashion. You get the arguments of the current function - that's all.
I've made a couple of modifications to your script to handle JavaScript's optional parameters. jsfiddle.net/LS6YJ
0

You are looking for typeof operator.

3 Comments

Yes, I could use the typeof operator to implement the exampleUsage function. But how can I obtain the arguments of a function from inside the function?
This doesn't answer the entire question, but it's a good start, at least. :)
Oh okay, if you need arguments then you can see built-in arguments array-like object. (Also mentioned by @Surreal in comments to your question).
0

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/

3 Comments

How does jQuery.type differ from the typeof operator, specifically?
For example native typeof function typeof(new Date) will return "object" but jQuery.type(new Date()) will return "date".
jQuery.type({}) this will return "object" (assosiative array) but jQuery.type([])​ this will return "array" while native javascript typeof will return object in both cases.
0

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
}

Comments

-4

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)

3 Comments

The OP is looking for a general purpose (aka reusable) function to check types, not general comments about the quality of a programming language.
Why is Javascript "bad for types"? It's possible to check the type of a function using the typeof operator. Also, it's possible to obtain the arguments of a function using arguments.
Specifically, why do you think Javascript is "bad"?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.