noImplicitCoercions
Summary
Section titled “Summary”- Rule available since:
v2.1.0 - Diagnostic Category:
lint/complexity/noImplicitCoercions - This rule isn’t recommended, so you need to enable it.
- This rule has an unsafe fix.
- The default severity of this rule is information.
- Sources:
- Same as
no-implicit-coercion
- Same as
How to configure
Section titled “How to configure”{ "linter": { "rules": { "complexity": { "noImplicitCoercions": "error" } } }}Description
Section titled “Description”Encourage use of explicit type conversion functions over their shorthand counterparts.
JavaScript (due to its dynamic typing) automatically coerces values to and from different types when applying certain operators. As such, one can use these operators as a “shorthand” for coercing values between different types:
const answer = +"42"; // 42 (coerced to number)
const myStr = "" + answer; // "42" (coerced to string)console.log(!!answer); // true (coerced to boolean)While these “implicit coercions” can save space, there are several reasons one may prefer to avoid them:
- Relying on these shortcuts can hurt readability, especially for newer developers less familiar with these patterns.
Writing
Boolean(value)orString(myNum)makes the type of the resulting value clear and explicit, as opposed to!!valueorfoo + ""(which may appear confusing at first glance). - TypeScript does not allow declaration merging for the built-in type coercion operators, unlike their more explicit function counterparts.
For instance,
+valuecannot be overridden to return a more specific type under certain conditions (as opposed toNumber(), whose method signatures can be customized to do exactly that).
This rule encourages the use of explicit type conversion functions like Boolean(), Number(), and String()
in favor of implicit operator conversions.
Disallowed patterns
Section titled “Disallowed patterns”A full list of constructs linted by this rule are as follows:
| Pattern | Target | Example |
|---|---|---|
| Double negation1 | Boolean | !!value |
| Unary plus | Number | +value |
| Double unary negation | Number | -(-value) |
| Subtraction with zero2 | Number | value - 0 |
| Multiplication with one2 | Number | value * 1 |
| Division with one2 | Number | value / 1 |
| Concatenation with an empty string2 | String | value + "", value + “ |
Bitwise NOT with indexOf3 | Check against -1 | ~arr.indexOf(value) |
Examples
Section titled “Examples”Invalid
Section titled “Invalid”!!foo;code-block.js:1:1 lint/complexity/noImplicitCoercions FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ℹ Implicit type conversions are hard to read and understand.
> 1 │ !!foo;
│ ^^^^^
2 │
ℹ Unsafe fix: Use Boolean() instead.
1 │ - !!foo;
1 │ + Boolean(foo);
2 2 │
+foo;code-block.js:1:1 lint/complexity/noImplicitCoercions FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ℹ Implicit type conversions are hard to read and understand.
> 1 │ +foo;
│ ^^^^
2 │
ℹ Unsafe fix: Use Number() instead.
1 │ - +foo;
1 │ + Number(foo);
2 2 │
-(-foo);code-block.js:1:1 lint/complexity/noImplicitCoercions FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ℹ Implicit type conversions are hard to read and understand.
> 1 │ -(-foo);
│ ^^^^^^^
2 │
ℹ Unsafe fix: Use Number() instead.
1 │ - -(-foo);
1 │ + Number(foo);
2 2 │
foo - 0;code-block.js:1:1 lint/complexity/noImplicitCoercions FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ℹ Implicit type conversions are hard to read and understand.
> 1 │ foo - 0;
│ ^^^^^^^
2 │
ℹ Unsafe fix: Use Number() instead.
1 │ - foo·-·0;
1 │ + Number(foo);
2 2 │
foo * 1;code-block.js:1:1 lint/complexity/noImplicitCoercions FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ℹ Implicit type conversions are hard to read and understand.
> 1 │ foo * 1;
│ ^^^^^^^
2 │
ℹ Unsafe fix: Use Number() instead.
1 │ - foo·*·1;
1 │ + Number(foo);
2 2 │
foo / 1;code-block.js:1:1 lint/complexity/noImplicitCoercions FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ℹ Implicit type conversions are hard to read and understand.
> 1 │ foo / 1;
│ ^^^^^^^
2 │
ℹ Unsafe fix: Use Number() instead.
1 │ - foo·/·1;
1 │ + Number(foo);
2 2 │
foo + "";code-block.js:1:1 lint/complexity/noImplicitCoercions FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ℹ Implicit type conversions are hard to read and understand.
> 1 │ foo + "";
│ ^^^^^^^^
2 │
ℹ Unsafe fix: Use String() instead.
1 │ - foo·+·"";
1 │ + String(foo);
2 2 │
'' + foo;code-block.js:1:1 lint/complexity/noImplicitCoercions FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ℹ Implicit type conversions are hard to read and understand.
> 1 │ ” + foo;
│ ^^^^^^^^
2 │
ℹ Unsafe fix: Use String() instead.
1 │ - ''·+·foo;
1 │ + String(foo);
2 2 │
baz += ``;code-block.js:1:1 lint/complexity/noImplicitCoercions FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ℹ Implicit type conversions are hard to read and understand.
> 1 │ baz += “;
│ ^^^^^^^^^
2 │
ℹ Unsafe fix: Use String() call instead.
1 │ - baz·+=·``;
1 │ + baz·=·String(baz);
2 2 │
~foo.indexOf(1);code-block.js:1:1 lint/complexity/noImplicitCoercions FIXABLE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ℹ Using binary operations instead of comparisons is harder to read and understand.
> 1 │ ~foo.indexOf(1);
│ ^^^^^^^^^^^^^^^
2 │
ℹ Unsafe fix: Compare with -1 instead.
1 │ - ~foo.indexOf(1);
1 │ + (foo.indexOf(1)·!==·-1);
2 2 │
Boolean(foo);Number(foo);String(foo);foo.indexOf(1) !== -1;`a${foo}`;tag`${foo}`;These are not flagged because they may have other effects on the produced value other than type coercion:
!foo;~foo;-foo;+1234;2 * foo;foo + 'bar';foo + 0; // has the potential to concatenate strings, unlike `foo - 0` which always produces a numberOptions
Section titled “Options”allowDoubleNegation
Section titled “allowDoubleNegation”Whether to allow or disallow the use of double negation (!!value) for Boolean coercions.
Default: false (disallow)
Examples of correct code with allowDoubleNegation set to true:
{ "linter": { "rules": { "complexity": { "noImplicitCoercions": { "options": { "allowDoubleNegation": true } } } } }}!!foo;While one could make an argument to add options for each individual disallowed pattern, the other variants are significantly less common and tend to suffer even more from readability issues. As such, the choice was made (for the time being) to only allow toggling double negation given its relatively high frequency.
If you have a strong case to selectively allow one of the other patterns, open a feature request on GitHub and we can discuss it there!
Related links
Section titled “Related links”Footnotes
Section titled “Footnotes”Copyright (c) 2023-present Biome Developers and Contributors.