Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inconsistent errors reported between tsc and VSCode #52813

Closed
frank-weindel opened this issue Feb 16, 2023 · 6 comments · Fixed by #53261
Closed

Inconsistent errors reported between tsc and VSCode #52813

frank-weindel opened this issue Feb 16, 2023 · 6 comments · Fixed by #53261
Assignees
Labels
Fix Available A PR has been opened for this issue Needs Investigation This issue needs a team member to investigate its status.

Comments

@frank-weindel
Copy link

frank-weindel commented Feb 16, 2023

Bug Report

The basic problem looks like this:

  1. I run tsc directly from the command line and get Set A of errors.
  2. VSCode instead shows Set B of errors which can be wildly different than Set A
  3. If I issue the TypeScript: Restart TS Server command to VSCode, I will then start to just see Set A errors in my IDE
  4. However... if I go and make a small change to a file I start only seeing Set B errors again.

Set B errors seem completely wrong since the tsc doesn't produce them. HOWEVER, a specfically unique error in Set B seems to be causing this weird behavior:

'Value' implicitly has type 'any' because it does not have a type annotation and is referenced directly
or indirectly in its own initializer.ts(7022)

If I solve this error with an explicit type assertion, the inconsistency goes away and I resume seeing Set A errors.

My project does rely on a deep set of types involving conditionals and generics. This seems to have something to do with causing this problem. I've provided a repository below with steps on how to reproduce. I would try to narrow the behavior down to a simpler project+repo but do not have the time at the moment.

Original Discord discussion

🔎 Search Terms

inconsistency, inconsistent, errors, ts language server,

🕗 Version & Regression Information

This issue was tested and occurs in TypeScript 4.9 and the latest nightly build as of this writing (5.0.0-dev.20230216).

⏯ Playground Link

Unfortunately I'm unable to reproduce this with the TS Playground

Repo+Branch that reproduces the issue

  • Navigate to Stepper.ts line 77. See the TSDoc comment there for reproducibility steps. It can some times take a few file modifications to trigger the behavior.
  • I was able to reproduce the same issue using GitHub Codespaces.

💻 Code

See Repo above.

🙁 Actual behavior

  • TypeScript errors reported by VSCode are inconsistent with the ones reported by running tsc via the command line.
  • VSCode can be temporarily made consistent by restarting the TS Server.
  • A single error seems to be causing TS+VSCode to act in this way.

🙂 Expected behavior

  • TypeScript errors reported by VSCode should always match with the ones reported by running tsc via the command line.
@RyanCavanaugh RyanCavanaugh added the Needs Investigation This issue needs a team member to investigate its status. label Feb 17, 2023
@RyanCavanaugh RyanCavanaugh added this to the TypeScript 5.1.0 milestone Feb 17, 2023
@gabritto
Copy link
Member

Hi @frank-weindel, I have been trying to reproduce this using the instructions you left, but so far I wasn't able to. If you're still able to repro this, could you repro it with logging enabled on tsserver, and post the tsserver logs here? That would help me investigate this issue. Thank you.

In case you don't already know how to do get a tsserver log:
(1) You can enable logging on vscode by going to your settings and looking for "Tsserver: log" setting, and setting it to "verbose".
image

(2) Once you have logging enabled, and you manage to reproduce the issue, you can then open the log by running the "TypeScript: Open TS Server log" command on vscode:
image

@frank-weindel
Copy link
Author

As requested!

Specifically what I did to reproduce was:

  • Open Stepper.ts in a tab
  • Restart TS Server to clear error
  • Use Cmd+P to open ProgressStepper.ts
  • Remove the unnecessary trailing comma on line 9 of ProgressStepper.ts
  • Without needing to even save, Stepper.ts lights up with the error

@gabritto
Copy link
Member

gabritto commented Mar 3, 2023

I think the following program captures the essence of this issue:

interface Some {}

class Foo<T=Some> {
    num: number = 0;
    Field: number = (this as Foo).num;
    Value = (this as Foo).num; // Ok
}

You don't get the circularity error reported on the above program, but you do get the error if you swap the Field and Value declarations:

interface Some {}

class Foo<T=Some> {
    num: number = 0;
    Value = (this as Foo).num; // Error
    Field: number = (this as Foo).num;
}

Playground link

Essentially, what is happening is that, if we type check property Field first, we succeed and we cache some types and variances, so that when we then type check Value, we don't run into a circularity and everything works. If we start by type checking Value instead, we run into a circularity. So whether we get the circularity error or not depends on the order in which we check those properties.

Translating that to the original reported issue, what happens is that, when we run the checker via tsc, we type check file Stepper.ts and then we check file ProgressStepper.ts. In an editor context, we sometimes check ProgressStepper.ts and then we check Stepper.ts, and when that happens, the circularity error is reported.

@RyanCavanaugh
Copy link
Member

Does adding variance annotation(s) to Stepper fix the issue?

@gabritto
Copy link
Member

gabritto commented Mar 3, 2023

Does adding variance annotation(s) to Stepper fix the issue?

Yes, computing variance for Stepper is how we run into the circularity when type checking Value.

@RyanCavanaugh
Copy link
Member

RyanCavanaugh commented Mar 3, 2023

Here's a variant repro I was trying out

function f() {
    const b = new Bar();
    // Uncomment to create error
    // console.log(b.Value);
}

class Bar<T> {
    num!: number;
    // Or swap these two lines
    Field: number = (this as Bar<any>).num;
    Value = (this as Bar<any>).num;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Fix Available A PR has been opened for this issue Needs Investigation This issue needs a team member to investigate its status.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants