58
votes

L'objet d'erreur à l'intérieur de la catch est de type inconnu

J'ai le code suivant:

try {
  phpDoc(vscode.window.activeTextEditor);
} catch (err) {
  console.error(err);
  vscode.window.showErrorMessage(err.message);
}

Cependant err.message obtient l'erreur L'objet est de type 'inconnu'.ts (2571) sur err. , mais je ne peux pas taper l'objet dans catch (err: error) .

Que dois-je faire? P >


2 commentaires

Vous pouvez utiliser le module Cast-Error pour traiter les deux problèmes principaux (JavaScript peut envoyer n'importe quelle valeur, et TypeScript inconnu le type d'erreur) avec lui: npmjs.com/package/cast-error


@Emilioplatzer Lorsque vous recommandez un package / service, il est conseillé de divulguer l'affiliation que l'on a avec ledit package.


5 Réponses :


29
votes

c'est parce que tout peut être lancé, donc inconnu .

try {
  phpDoc(vscode.window.activeTextEditor);
} catch (err) {
  console.error(err);
  if (err instanceof Error) {
    vscode.window.showErrorMessage(err.message);
  } else {
    // do something else with what was thrown, maybe?
    // vscode.window.showErrorMessage(String(err));
  }
}

Vous devrez vérifier que le err est en fait une erreur pour le réduire avant d'accéder à la propriété Message .

const fn = () => {
  throw 'foo';
};
try {
  fn();
} catch(e) {
  console.log(e);
  console.log(e instanceof Error);
  console.log(e === 'foo');
}


4 commentaires

Si moi, en tant qu'auteur, j'ai écrit la fonction qui lance l'erreur, ne serait-il pas correct pour moi d'annoter l'erreur avec le type plus spécifique? Pourquoi TypeScript m'empêche-t-il de faire ça?


Vous pouvez j'espère que si votre fonction lance une erreur, elle lancera une erreur de votre type noté, mais il y a toujours le risque qu'il lance une erreur différente et inattendue - donc annoter le type de l'erreur ( dans un achèvement anormal) n'est pas possible. (Si vous voulez être parfaitement à sa sécurité, ce qui strict essaie d'implémenter)


Mais n'est-ce pas vrai pour toute fonction qui appelle toute autre fonction qui pourrait lancer ou pour être là une exception système, nous sommes toujours en mesure d'annoter le type de retour pour de telles fonctions


Oui, le type de rendement normal de n'importe quelle fonction est facile à annoter - mais les exceptions, en revanche, sont imprévisibles (elles pourraient être n'importe quoi, pas seulement celles que vous espérez), donc leur type potentiel "d'erreur" ne peut pas être annoté. Une fonction qui se termine normalement peut être bien comprise à l'avance par le vérificateur de type. Une fonction qui ne se termine pas normalement signifie que quelque chose aurait pu se produire.



60
votes

En tant que réponse supplémentaire à assurementformance 68240891/11407695 "> un :

jusqu'à TypeScript 4.0, le Catch Les liaisons de la clause ont été définies sur n'importe quel permettant ainsi un accès facile au Message Propriété. Ceci n'est pas sûr car il n'est pas garanti que ce qui est lancé sera hérité du Erreur Prototype - Il se produit juste que nous ne jetons rien d'autre que les erreurs comme meilleure pratique: p >

(() => {
    try {
        throw new Error("ouch!");
    } catch(err: unknown) {
        console.log(err.message); //Object is of type 'unknown'
    }
})();


2 commentaires

Donc, pour le corriger, faites-vous useUnkNownIncatchVariables false à nouveau?


@TheProcoder bien, c'est une façon d'approcher cela. Le reste dépend de la façon dont vous êtes dévoué à la vérification stricte de type: bien sûr, le moyen le plus sûr est d'effectuer réellement les vérifications d'exécution (qui doublent comme gardes) avec instanceof (voir la réponse de la certaine performance), la plus "honnête "Way sans taxes d'exécution est une affirmation de type (car nous" supposons "que le paramètre catch est d'un certain type), et l'approche" allez-y, s'il vous plaît "est, oui, explicitement Définition du useUnkNownInCatchVariables sur FALSE (voir la réponse de Dast)



33
votes

Si vous ne souhaitez pas modifier tout votre code après la mise à niveau de votre type TypeScript mais que vous êtes en mode strict, vous pouvez ajouter l'option du compilateur suivant après l'option stricte pour l'écraser, comme cela a été indiqué dans Réponse d'Oleg :

tsconfig.json

{
  "compilerOptions": {
    [...]
    "strict": true,
    "useUnknownInCatchVariables": false,
    [...]
    },
  },
}


5 commentaires

Vous ne pouvez pas faire de commentaires dans JSON.


@Boris c'est à la fois correct et non - je suppose que l'OP utilise JSONC également connu sous le nom de "JSON avec commentaires" et disponible avec Le Code Visual Studio IDE (qui est souvent utilisé avec les projets TypeScript) qui rend leur exemple de code valide. Pourtant, je suis enclin à convenir que l'on ne peut pas mettre des commentaires dans JSON :)


@Boris aucune idée de la façon dont cela est pertinent pour la réponse réelle, lorsqu'elle est clairement utilisée par exemple.


@Petar C'était pertinent pour moi parce que je devais les supprimer après la copie et le collage.


Les commentaires sont autorisés dans les fichiers tsconfig.json, voir github.com/microsoft/typescript/issues/4987 < / a>



0
votes

ma version TypeScript est sous 4.0 , et je ne peux pas le faire fonctionner à nouveau, puis j'ai créé une fonction auxiliaire pour normaliser les erreurs, comme suivre:

try {
  phpDoc(vscode.window.activeTextEditor);
} catch (err) {
  const e = normalizeError(err);
  console.error(err);
  vscode.window.showErrorMessage(e.message);
}


0 commentaires

0
votes

Vous ne pouvez pas écrire une annotation spécifique pour la variable de clause Catch dans TypeScript, c'est parce que dans JavaScript, une clause Catch attrapera toute exception qui est lancée, pas seulement des exceptions d'un type spécifié.

Dans TypeScript, si vous voulez attraper juste un type d'exception spécifique, vous devez attraper tout ce qui est lancé, vérifiez si c'est le type d'exception que vous souhaitez gérer, et sinon, jetez-le à nouveau. P >

Signification : Assurez-vous que l'erreur qui est lancée est d'abord une erreur Axios, avant de faire quoi que ce soit.

Solution 1

en utilisant l'affirmation de type
Utilisez AxioSerror pour lancer une erreur

import axios from "axios"

try {
    // do something
} catch (err) {
    // check if the error is an axios error
    if (axios.isAxiosError(err)) {
        // console.log(err.response?.data)
        if (!err?.response) {
            console.log("No Server Response");
        } else if (err.response?.status === 400) {
            console.log("Missing Username or Password");
        } else {
            console.log("Login Failed");
        } 
    } 
}
Solution 2

Vérifiez si l'erreur est une erreur Axios en premier, avant de faire quoi que ce soit

xxx pre>


0 commentaires