Rule proposal: no-implicit-conversion
axetroy opened this issue · 3 comments
Description
When using the +/- operator with strings and numbers.
There are many traps here, and things can go wrong.
e.g.
let result = '5' + 3;
console.log(result); // '53' - String concatenation
let result = '5' - 3;
console.log(result); // 2 - The string is converted to a number
result = 3 + '5';
console.log(result); // '35' - Still string concatenation
let result = '10' - 3;
console.log(result); // 7 - The string '10' is converted to the number 10
result = '5' - '2';
console.log(result); // 3 - Both strings are converted to numbers and then subtracted
I know, no one would write code like this in the real world
But there will be the following situation
function foo() {
// ...other logic
return "5"
}
// ... other logic
const bar = foo() + 5 // ❌
We should check that left and right expression are of the same type to avoid implicit conversion.
It is feasible when we can infer its type, skip check when found any
/unknown
/never
.
There is no possibility of false positives
Fail
Plus operator:
const foo = "5" // numberic
// ... other logic
const bar = foo + 5 // ❌
function foo() {
return "5"
}
// ... other logic
const bar = foo() + 5 // ❌
Minus operator:
const foo = "10"
// ...other logic
const bar = foo - 5 // ❌
Type Annotation:
let foo: string
// ...other logic
const bar = foo - 5 // ❌
let foo = (): string => {}
// ...other logic
const bar = foo() - 5 // ❌
function foo (bar: string) {
bar - 5 // ❌
}
Pass
const foo = "5"
// ... other logic
const bar = Number(foo) + 5 // ✅
function foo() {
return "5"
}
// ... other logic
const bar = Number(foo()) + 5 // ✅
Minus operator:
const foo = "10"
// ...other logic
const bar = Number(foo) - 5 // ✅
Proposed rule name
no-implicit-conversion
Additional Info
No response
This is hard to detect, but
1e13 - new Date(); // -> number
1e13 + new Date(); // -> string
If the code is in TS this is redundant, so the “type annotation” examples shouldn’t be considered.
For the rest, this would only work in the limited cases where the value (and therefore its type) is defined locally. It kinda makes sense as a rule but also people who care about this just use TypeScript. By this I mean that outside TS people generally take advantage of JS’ dynamicity and don’t like the verbosity of Number(str) - 1
.
The only scenario where this would actually be beneficial (i.e. prevent bugs) is on str + number
, but it feels like this rarely happens when str
is declared locally.
Just my 2c, this rule wouldn’t affect me as I use TS almost exclusively.
TypeScript can detect this. If user use JavaScript, they need to tolerate the type-safe problems about JavaScript. IMO, ESLint should not repeat the functions belonging to TS.