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".
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
Thanks @Trott for your code, I just used the same code and added with a real time working example for the benefit of others.
<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_
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]";
}
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_
This behavior is guaranteed by the ECMAScript Language Specification.
When the toString method is called, the following steps are taken:
- If the this value is undefined, return "[object Undefined]".
- If the this value is null, return "[object Null]".
- Let O be the result of calling ToObject passing the this value as the argument.
- Let class be the value of the [[Class]] internal property of O.
- 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.
Source: Stackoverflow.com