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
}
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
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
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"]);
}
You are looking for typeof operator.
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/
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
}
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)
©2020 All rights reserved.