@typescript-eslint/only-throw-error
Disallow throwing values that are not `Error` objects
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#
Reported:
function load(path: string, status: number) {
if (!path) throw "path is required";
if (status === 404) throw { status };
throw undefined;
}Not reported:
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. |
function fail(reason: any) {
throw reason;
}In strict mode, the error in a catch is unknown. With allowThrowingUnknown: false, you can still throw it again:
function parse(text: string): unknown {
try {
return JSON.parse(text);
} catch (error) {
console.error("invalid JSON");
throw error;
}
}function parse(text: string): unknown {
try {
return JSON.parse(text);
} catch (error) {
console.error("invalid JSON");
throw error;
}
}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" }.
class Redirect {
constructor(public url: string) {}
}
throw new Redirect("/login");