我有以下代码:
try {
phpDoc(vscode.window.activeTextEditor);
} catch (err) {
console.error(err);
vscode.window.showErrorMessage(err.message);
}
但是err.message
得到错误Object is of type 'unknown'.ts(2571)
,err.
但我无法在中键入对象catch (err: Error)
。
我该怎么办?
我有以下代码:
try {
phpDoc(vscode.window.activeTextEditor);
} catch (err) {
console.error(err);
vscode.window.showErrorMessage(err.message);
}
但是err.message
得到错误Object is of type 'unknown'.ts(2571)
,err.
但我无法在中键入对象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 但处于严格模式后更改所有代码,则可以在覆盖它的选项之后添加以下编译器选项,正如Oleg 的回答strict
中所暗示的那样:
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');
}
在访问该属性之前,您需要检查这err
实际上是一个错误以缩小范围。message
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版本低于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);
}