Skip to content

TS7022 (circular reference) on simple assignments in a loop #59074

Closed as not planned
@Ghabriel

Description

@Ghabriel

🔎 Search Terms

TS7022, implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer, circular reference, circular type

🕗 Version & Regression Information

  • This is the behavior in every version (3.3.3+) I tried, and I reviewed the FAQ for entries about circular references

⏯ Playground Link

https://www.typescriptlang.org/play/?ts=5.5.2#code/CYUwxgNghgTiAEYD2A7AzgF3hAlikAXPJjHgOYDcAUBCFhiJkSefAD7woCuEE8AvJx4RqVAGZIY8ABS0sOAfAAMFeAoA82PCAB0tFGQwALVTgDUZgJTwA3lXiJUmREdiLc+ANo4AutQc4YjIMzvxhLrDWNgC+9o7oWFAQaEgAwq5SgmAZ-vAhWIJJKemw1LFAA

💻 Code

declare const line: string;
let test: string | null = null;

for (let i = 0; i < line.length; i++) {
  const char = line[i];
  if (test === char) {}
  const alsoChar = char;
  test = alsoChar;
}

🙁 Actual behavior

The following error is triggered:
'alsoChar' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.(7022)

🙂 Expected behavior

No errors. char is clearly a string and alsoChar is just a copy of it, so there shouldn't be any type confusion and/or circularity. test isn't even read from, except in the empty if statement.

Additional information about the issue

  • Removing the empty if on line 6 fixes the error.
  • Replacing the if on line 6 by if (test !== char) {} also produces the error, but if (test! < char) {} doesn't.
  • Replacing line 2 by let test: string | undefined = undefined; also produces the error, but let test: string | undefined; doesn't.

This version also reproduces the issue:

declare const line: string;
let test: boolean | null = null;

for (let i = 0; i < line.length; i++) {
  const char = line[i];
  if (test !== char) {}
  const alsoChar = char === ""; // <- using a simple comparison
  test = alsoChar;
}

Same for this one:

declare const line: string;
let test: string | null = null;

for (let i = 0; i < line.length; i++) {
  const char = line[i];
  if (test !== char) {}
  const alsoChar = char[0]; // <- changing char to char[0]
  test = alsoChar;
}

But this one doesn't:

declare const line: string;
let test: string | null = null;

for (let i = 0; i < line.length; i++) {
  const char = line[i];
  if (test !== char) {}
  const alsoChar = char.charAt(0); // <- char.charAt(0) instead of char[0]
  test = alsoChar;
}

Another interesting point is that despite the error, the tooltip does show const alsoChar: string as expected. This is recent, though: v5.3.3 shows the type as any, whereas v5.4.5 shows it as string.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Not a DefectThis behavior is one of several equally-correct options

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions