web-dev-qa-db-fra.com

vérification de l'erreur typeof dans JS

En JS, il ne semble pas possible de vérifier si un argument transmis à une fonction est en réalité du type "erreur" ou une instance de Erreur.

Par exemple, ceci n'est pas valide:

typeof err === 'error'

puisqu'il n'y a que 6 types possibles (sous forme de chaînes):

L'opérateur typeof renvoie les informations de type sous forme de chaîne. typeof renvoie six valeurs possibles:

"nombre", "chaîne", "booléen", "objet", "fonction" et "indéfini".

MSDN

Mais que se passe-t-il si j'ai un cas d'utilisation simple comme celui-ci:

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

alors quel est le meilleur moyen de déterminer si un argument est une instance de Error?

l’opérateur instanceof at-il de l’aide?

88
Alexander Mills

Vous pouvez utiliser l'opérateur instanceof .

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

J'ai posé la question initiale - la réponse de @Trott est sûrement la meilleure.

Cependant, JS étant un langage dynamique et le nombre d'environnements d'exécution JS étant très nombreux, l'opérateur instanceof peut échouer, en particulier dans le développement front-end lors du franchissement de limites telles que les iframes. Voir: https://github.com/mrdoob/three.js/issues/5886

Si vous êtes d'accord avec la frappe de canard, cela devrait être bon:

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

Personnellement, je préfère les langages à typage statique, mais si vous utilisez un langage dynamique, il vaut mieux adopter un langage dynamique pour ce qu’il est, plutôt que de le forcer à se comporter comme un langage à typage statique.

si vous voulez être un peu plus précis, vous pouvez le faire:

   let isError = function(e){
     return e && e.stack && e.message && typeof e.stack === 'string' 
            && typeof e.message === 'string';
    }
17
Alexander Mills
var myError = new Error('foo');
myError instanceof Error // true
var myString = "Whatever";
myString instanceof Error // false

Le seul problème avec ceci est 

myError instanceof Object // true

Une alternative à cela serait d'utiliser la propriété constructeur.

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

Bien qu'il faille noter que cette correspondance est très spécifique, par exemple:

myError.constructor === TypeError // false
2
Tom

Vous pouvez utiliser obj.constructor.name pour vérifier la "classe" d'un objet https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name#Function_names_in_classes

Par exemple

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

La ligne ci-dessus consignera "Erreur", qui correspond au nom de classe de l'objet. Cela peut être utilisé avec toutes les classes en javascript, si la classe n'utilise pas une propriété nommée "name" 

0
KimboKast

Ou utilisez ceci pour différents types d'erreurs

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