catch中的错误对象的类型未知



我有以下代码:

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

然而,err.messageerr.上得到错误Object is of type 'unknown'.ts(2571),但我无法在catch (err: Error)中键入对象。

我该怎么办?

作为CertainPerformance的补充答案:

在TypeScript 4.0之前,catch子句绑定被设置为any,从而允许轻松访问message属性。这是不安全的,因为它不能保证抛出的东西将继承自Error原型-它只是发生了,作为最佳实践,我们除了错误之外什么都不抛出:

(() => {
try {
const myErr = { code: 42, reason: "the answer" };
throw myErr; //don't do that in real life
} catch(err) {
console.log(err.message); //undefined
}
})();

TypeScript 4.0引入了一个更安全的catch子句选项,允许您将参数注释为unknown,迫使您进行显式类型断言,或者更好地进行类型保护(这使子句在编译时和运行时都是安全的(。

然而,为了避免破坏大多数代码库,您必须明确选择新的行为:

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

TypeScript 4.4引入了一个名为useUnknownInCatchVariables的新编译器选项,使此行为成为强制性的。默认情况下,它是false,但如果您打开了strict选项(正如您应该打开的那样(,它就会打开,这很可能是您最初出现错误的原因。

如果你不想在升级TypeScript后更改所有代码,但处于严格模式,你可以在strict选项后添加以下编译器选项来覆盖它,正如Oleg的回答所暗示的那样:

tsconfig.json

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

"strict": true,useUnknownInCatchVariables设置为true,然后"useUnknownInCatchVariables": false,覆盖该值并将其设置回false。

这是因为任何都可以抛出,因此unknown

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

在访问message属性之前,您需要检查err是否确实是一个错误以缩小其范围。

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

您不能在typescript中为catch子句变量编写特定的注释,这是因为在javascript中,catch子句将捕获抛出的任何异常,而不仅仅是指定类型的异常。

在typescript中,如果你只想捕获特定类型的异常,你必须捕获抛出的任何异常,检查它是否是你想要处理的异常类型,如果不是,则再次抛出。

意思是:在做任何事情之前,首先确保抛出的错误是axios错误。

溶液1

使用类型断言
使用AxiosError投射错误

import  { AxiosError } from 'axios';
try {
// do some api fetch
} catch (error) {
const err = error as AxiosError
// 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");
}  
}
溶液2

在做任何之前,首先检查错误是否是axios错误

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

我的TypeScript版本在4.0下,我无法使其再次工作,然后我创建了一个辅助函数来规范错误,如下所示:

interface INormalizedError {
/**
* Original error.
*/
err: unknown;
/**
* Is error instance?
*/
isError: boolean;
/**
* Error object.
*/
error?: Error;
/**
* Call stack.
*/
stack?: Error['stack'];
/**
* Error message.
*/
message: string;
toString(): string;
}
/**
* Normalize error.
*
* @param err Error instance.
* @returns Normalized error object.
*/
function normalizeError(err: unknown): Readonly<INormalizedError> {
const result: INormalizedError = {
err,
message: '',
isError: false,
toString() {
return this.message;
}
};
if (err instanceof Error) {
result.error = err;
result.message = err.message;
result.stack = err.stack;
result.isError = true;
result.toString = () => err.toString();
} else if (typeof err === 'string') {
result.error = new Error(err);
result.message = err;
result.stack = result.error.stack;
} else {
const aErr = err as any;
if (typeof err === 'object') {
result.message = aErr?.message ? aErr.message : String(aErr);
result.toString = () => {
const m = typeof err.toString === 'function' ? err.toString() : result.message;
return (m === '[object Object]') ? result.message : m;
};
} else if (typeof err === 'function') {
return normalizeError(err());
} else {
result.message = String(`[${typeof err}] ${aErr}`);
}
result.error = new Error(result.message);
result.stack = aErr?.stack ? aErr.stack : result.error.stack;
}
return result;
}

一个使用示例:

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

最新更新