sindresorhus / eslint-plugin-unicorn

More than 100 powerful ESLint rules
MIT License
4.25k stars 367 forks source link

Incorrect `no-for-loop` fix for strings in TypeScript #2205

Open andrmoel opened 1 year ago

andrmoel commented 1 year ago

Setup:

I use the no-for-loop rule to auto fix my code. My code iterates through a string value. The autofix changes my code wrong and assumes that my string is an object.

Original Code

function renderAnimatedChars(formattedValue: string): void {
    for (let i = 0; i < formattedValue.length; i++) {
        const char = formattedValue[i];

        console.log(`Key: ${i} Value: ${char}`);
    }
}

Code after autofix

    function renderAnimatedChars(formattedValue: string): void {
        for (const [i, char] of formattedValue.entries()) {
            console.log(`Key: ${i} Value: ${char}`);
        }
    }

The problem is that entries is not a valid function on a string. TS2239


An interesting observation is, that this appears only when the type definition is given by the function parameter. The autofix works correctly if a const parameter is used. The autofix does not change this code.

Original Code

    function foo(): void {
        const formattedValue = 'bla bla';

        for (let i = 0; i < formattedValue.length; i++) {
            const char = formattedValue[i];

            console.log(`Key: ${i} Value: ${char}`);
        }
    }
simllll commented 11 months ago

Similar issue on my side,

const ripplesResult = el.getElementsByClassName('v-ripple__animation');

if (ripplesResult) {
for (let i = 0; i < ripplesResult.length; i++) {
... 
}
}

If I auto fix it, it changes the for loop to:

for (const node: Node of ripplesResult) {

which then has two issues:

  1. TS2483: The left-hand side of a  for...of  statement cannot use a type annotation.
  2. TS2488: Type  HTMLCollectionOf  must have a  [Symbol.iterator]()  method that returns an iterator.