En JS, no parece posible verificar si un argumento pasado a una función es realmente del tipo 'error' o una instancia de Error.
Por ejemplo, esto no es válido:
typeof err === 'error'
ya que solo hay 6 tipos posibles (en forma de cadenas):
El operador typeof devuelve información de tipo como una cadena. Hay seis valores posibles que typeof devuelve:
"número", "cadena", "booleano", "objeto", "función" e "indefinido".
Pero, ¿y si tengo un caso de uso simple como este?
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); } }Entonces, ¿cuál es la mejor manera de determinar si un argumento es una instancia de Error?
es el operador instanceof de alguna ayuda?
Puede usar el operador instanceof (¡pero vea la advertencia a continuación!).
var myError = new Error('foo'); myError instanceof Error // true var myString = "Whatever"; myString instanceof Error // false Lo anterior no funcionará si el error se produjo en una ventana/marco/iframe diferente de donde se está realizando la comprobación. En ese caso, la instanceof Error devolverá falso, incluso para un objeto de Error . En ese caso, el enfoque más fácil es tipear pato.
if (myError && myError.stack && myError.message) { // it's an error, probably } Sin embargo, la tipificación pato puede producir falsos positivos si tiene objetos que no son errores y que contienen propiedades de stack y message .
Hice la pregunta original: la respuesta de @Trott es seguramente la mejor.
Sin embargo, dado que JS es un lenguaje dinámico y que hay tantos entornos de tiempo de ejecución de JS, el operador instanceof puede fallar, especialmente en el desarrollo front-end cuando cruza límites como iframes. Ver: https://github.com/mrdoob/three.js/issues/5886
Si está de acuerdo con escribir pato, esto debería ser bueno:
let isError = function(e){ return e && e.stack && e.message; }Personalmente, prefiero los lenguajes tipificados estáticamente, pero si está utilizando un lenguaje dinámico, es mejor adoptar un lenguaje dinámico por lo que es, en lugar de obligarlo a comportarse como un lenguaje tipificado estáticamente.
Si quisieras ser un poco más preciso, podrías hacer esto:
let isError = function(e){ return e && e.stack && e.message && typeof e.stack === 'string' && typeof e.message === 'string'; }Puede usar Object.prototype.toString para verificar fácilmente si un objeto es un Error , que también funcionará para diferentes marcos.
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([]));Este comportamiento está garantizado por la especificación del lenguaje ECMAScript.
Cuando se llama al método toString, se toman los siguientes pasos:
- Si este valor no está definido, devuelve "[objeto no definido]".
- Si este valor es nulo, devuelve "[objeto Nulo]".
- Sea O el resultado de llamar a ToObject pasando este valor como argumento.
- Sea class el valor de la propiedad interna [[Class]] de O.
- Devuelve el valor de cadena que es el resultado de concatenar las tres cadenas "[objeto", clase y "]".
Propiedades de las instancias de error :
Las instancias de error heredan propiedades del objeto prototipo Error y su valor de propiedad interna
[[Class]]es "Error". Las instancias de error no tienen propiedades especiales.