[javascript] checking for typeof error in JS

In JS it doesn't seem possible to check if an argument passed to a function is actually of the type 'error' or an instance of Error.

For example, this is not valid:

typeof err === 'error'

since there are only 6 possible types (in the form of strings):

The typeof operator returns type information as a string. There are six possible values that typeof returns:

"number", "string", "boolean", "object", "function" and "undefined".

MSDN

But what if I have a simple use case like this:

function errorHandler(err) {

    if (typeof err === 'error') {
        throw err;
    }
    else {
        console.error('Unexpectedly, no error was passed to error handler. But here is the message:',err);
    }
}

so what is the best way to determine if an argument is an instance of Error?

is the instanceof operator of any help?

This question is related to javascript node.js

The answer is


Thanks @Trott for your code, I just used the same code and added with a real time working example for the benefit of others.

_x000D_
_x000D_
<html>_x000D_
<body >_x000D_
_x000D_
<p>The **instanceof** operator returns true if the specified object is an instance of the specified object.</p>_x000D_
_x000D_
_x000D_
_x000D_
<script>_x000D_
 var myError = new Error("TypeError: Cannot set property 'innerHTML' of null"); // error type when element is not defined_x000D_
 myError instanceof Error // true_x000D_
 _x000D_
 _x000D_
 _x000D_
 _x000D_
 function test(){_x000D_
 _x000D_
 var v1 = document.getElementById("myid").innerHTML ="zunu"; // to change with this_x000D_
 _x000D_
 try {_x000D_
    var v1 = document.getElementById("myidd").innerHTML ="zunu"; // exception caught_x000D_
    } _x000D_
    _x000D_
 catch (e) {_x000D_
    if (e instanceof Error) {_x000D_
   console.error(e.name + ': ' + e.message) // error will be displayed at browser console_x000D_
    }_x000D_
  }_x000D_
  finally{_x000D_
  var v1 = document.getElementById("myid").innerHTML ="Text Changed to Zunu"; // finally innerHTML changed to this._x000D_
 }_x000D_
 _x000D_
 }_x000D_
 _x000D_
</script>_x000D_
<p id="myid">This text will change</p>_x000D_
<input type="button" onclick="test();">_x000D_
</body>_x000D_
</html>
_x000D_
_x000D_
_x000D_


Or use this for different types of errors

function isError(val) {
  return (!!val && typeof val === 'object')
    && ((Object.prototype.toString.call(val) === '[object Error]')
      || (typeof val.message === 'string' && typeof val.name === 'string'))
}

var myError = new Error('foo');
myError instanceof Error // true
var myString = "Whatever";
myString instanceof Error // false

Only problem with this is

myError instanceof Object // true

An alternative to this would be to use the constructor property.

myError.constructor === Object // false
myError.constructor === String // false
myError.constructor === Boolean // false
myError.constructor === Symbol // false
myError.constructor === Function // false
myError.constructor === Error // true

Although it should be noted that this match is very specific, for example:

myError.constructor === TypeError // false

You can use obj.constructor.name to check the "class" of an object https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name#Function_names_in_classes

For Example

var error = new Error("ValidationError");
console.log(error.constructor.name);

The above line will log "Error" which is the class name of the object. This could be used with any classes in javascript, if the class is not using a property that goes by the name "name"


I asked the original question - @Trott's answer is surely the best.

However with JS being a dynamic language and with there being so many JS runtime environments, the instanceof operator can fail especially in front-end development when crossing boundaries such as iframes. See: https://github.com/mrdoob/three.js/issues/5886

If you are ok with duck typing, this should be good:

let isError = function(e){
 return e && e.stack && e.message;
}

I personally prefer statically typed languages, but if you are using a dynamic language, it's best to embrace a dynamic language for what it is, rather than force it to behave like a statically typed language.

if you wanted to get a little more precise, you could do this:

   let isError = function(e){
     return e && e.stack && e.message && typeof e.stack === 'string' 
            && typeof e.message === 'string';
    }

You can use Object.prototype.toString to easily check if an object is an Error, which will work for different frames as well.

function isError(obj){
    return Object.prototype.toString.call(obj) === "[object Error]";
}

_x000D_
_x000D_
function isError(obj){
    return Object.prototype.toString.call(obj) === "[object Error]";
}
console.log("Error:", isError(new Error));
console.log("RangeError:", isError(new RangeError));
console.log("SyntaxError:", isError(new SyntaxError));
console.log("Object:", isError({}));
console.log("Array:", isError([]));
_x000D_
_x000D_
_x000D_

This behavior is guaranteed by the ECMAScript Language Specification.

Object.prototype.toString:

When the toString method is called, the following steps are taken:

  1. If the this value is undefined, return "[object Undefined]".
  2. If the this value is null, return "[object Null]".
  3. Let O be the result of calling ToObject passing the this value as the argument.
  4. Let class be the value of the [[Class]] internal property of O.
  5. Return the String value that is the result of concatenating the three Strings "[object ", class, and "]".

Properties of Error Instances:

Error instances inherit properties from the Error prototype object and their [[Class]] internal property value is "Error". Error instances have no special properties.