Linter · Rules
@typescript-eslint/no-unused-expressions
Disallow statements that compute a value and do nothing with it
A statement such as user.name; or count + 1; computes a value and throws it away. It's usually a mistake, like a call without its (), a === that was meant to be =, or a line left behind after an edit.
Calls, new, assignments, await, delete, void, import(), and directives such as "use strict" do something, so they aren't reported. Neither are user && user.save(); and user.isNew ? user.create() : user.update();, which are short ways to write an if. The rule looks through as, !, and type arguments, so save as unknown; is reported like save;.
This rule is on by default in TypeScript files.
Configure
On by default as a warning. To turn it off:
[lint.rules]
"@typescript-eslint/no-unused-expressions" = "off" # or "error"
Every option, set to its default:
[lint.rules]
"@typescript-eslint/no-unused-expressions" = ["warn", {
allowShortCircuit = true,
allowTernary = true,
allowTaggedTemplates = false,
enforceForJSX = false,
ignoreDirectives = false,
}]
Examples
Reported:
declare const user: { name?: string; save(): void };
user.save;
user.name === "admin";
user?.name;
user.name!;
Not reported:
declare const user: { name?: string; save(): void };
user.save();
user.name = "admin";
user?.save();
Options
| Option | Default | What it does |
|---|---|---|
allowShortCircuit | true | Allow a && b(), a || b(), and a ?? b(), if the right side would be allowed as a statement. |
allowTernary | true | Allow a ? b() : c(), if both branches would be allowed as statements. |
allowTaggedTemplates | false | Allow a tagged template such as sql`...` as a statement. |
enforceForJSX | false | Also report a JSX element as a statement. |
ignoreDirectives | false | Allow strings at the start of a file or a function when ecmaVersion is 3, which has no directives. |
With an ESLint config file the defaults are typescript-eslint's: every option is false.
By default, you can use && instead of an if:
declare const user: { save(): void } | undefined;
user && user.save();
The right side still needs to do something:
declare const user: { save(): void } | undefined;
user && user.save;
declare const user: { isNew: boolean; create(): void; update(): void };
user.isNew ? user.create() : user.update();
declare const user: { isNew: boolean; create(): void; update(): void } | undefined;
user && user.update();
user?.isNew ? user.create() : user?.update();
declare function sql(strings: TemplateStringsArray): void;
sql`DELETE FROM sessions`;
<p>Saved</p>;