@typescript-eslint/only-throw-error
Disallow throwing values that are not Error objects
Also called typescript-eslint/only-throw-error, typescript/only-throw-error
You can throw any value, but only an Error records the stack where it was created. Code that catches it also expects an Error. With throw "not found", error.message is undefined and error instanceof Error is false.
By default, you can throw values of type any or unknown, and you can rethrow an error that you caught.
bun lint --type-aware turns this rule on in TypeScript files.
Configure#
Off by default. This rule needs types, so turning it on makes bun lint type check your code first.
[lint.rules]
"@typescript-eslint/only-throw-error" = "error" # or "warn"Every option, set to its default:
[lint.rules]
"@typescript-eslint/only-throw-error" = ["error", {
allowThrowingAny = true,
allowThrowingUnknown = true,
allowRethrowing = true,
allow = [], # list of strings or objects
}]Examples#
function load(path: string, status: number) {
if (!path) throw "path is required"Expected an error object to be thrown.;
if (status === 404) throw { status }Expected an error object to be thrown.;
throw undefinedDo not throw undefined.;
}class HttpError extends Error {
constructor(public status: number) {
super(`Request failed with ${status}`);
}
}
function load(path: string, status: number) {
if (!path) throw new Error("path is required");
throw new HttpError(status);
}Options#
| Option | Default | What it does |
|---|---|---|
allowThrowingAny | true | Allow throwing a value of type any. |
allowThrowingUnknown | true | Allow throwing a value of type unknown. |
allowRethrowing | true | Allow throwing the error from catch (error), from .catch(error => ...), and from the second callback of .then(), whatever its type. |
allow | [] | Other types you can throw. |
{ "allowThrowingAny": false }1 problemfunction fail(reason: any) {
throw reasonExpected an error object to be thrown.;
}In strict mode, the error in a catch is unknown. With allowThrowingUnknown: false, you can still throw it again:
{ "allowThrowingUnknown": false }No problemsfunction parse(text: string): unknown {
try {
return JSON.parse(text);
} catch (error) {
console.error("invalid JSON");
throw error;
}
}{ "allowThrowingUnknown": false, "allowRethrowing": false }1 problemfunction parse(text: string): unknown {
try {
return JSON.parse(text);
} catch (error) {
console.error("invalid JSON");
throw errorExpected an error object to be thrown.;
}
}Each allow entry is a type name, or an object that also says where the type comes from: { "from": "file", "name": "Redirect" } for your own code, { "from": "lib", "name": "Response" } for a built-in type, or { "from": "package", "name": "Redirect", "package": "my-router" }.
{ "allow": [{ "from": "file", "name": "Redirect" }] }No problemsclass Redirect {
constructor(public url: string) {}
}
throw new Redirect("/login");