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

A series of nested loops, undefined and in checks results in incorrect implicit any #45638

Open
frigus02 opened this issue Aug 30, 2021 · 2 comments
Assignees
Labels
Needs Investigation This issue needs a team member to investigate its status. Rescheduled This issue was previously scheduled to an earlier milestone

Comments

@frigus02
Copy link
Contributor

frigus02 commented Aug 30, 2021

Bug Report

A series of nested loops, undefined and in checks results in incorrect implicit any.

I don't know what is really causing this. It seems this might be a weird edge case where type inference fails?

🔎 Search Terms

noImplicitAny, inference

🕗 Version & Regression Information

This changed between versions 4.3.5 and 4.4.2

⏯ Playground Link

Playground link with relevant code

💻 Code

interface MyObj { id?: string; }
declare var objects: MyObj[]|undefined;

if (objects) {
  for (const _ of []) {
    const map: {[key:string]: string|undefined} = {};

    for (const obj of objects) {
      //       ~~~ 'obj' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.(7022)
      const id = obj.id!;
      //    ~~ 'id' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.(7022)
      if (id in map) {
        console.log(id);
      }
    }
  }
}

🙁 Actual behavior

In version 4.4.2 the above code fails to compile with the 2 errors.

Any of the following changes cause it compile without errors:

  • Remove |undefined from the objects type.
  • Remove the outer for (const _ of []) loop
  • Remove if (id in map)
  • Add a type annotation to the id variable: const id: string = obj.id!

🙂 Expected behavior

The code should compile without errors as it did in version 4.3.5.

@andrewbranch andrewbranch added the Needs Investigation This issue needs a team member to investigate its status. label Sep 2, 2021
@andrewbranch andrewbranch added this to the TypeScript 4.5.0 milestone Sep 2, 2021
@frigus02
Copy link
Contributor Author

frigus02 commented Sep 3, 2021

I have another example. Not entirely sure it's the same but it seems related to me:

function doSth(items: unknown[], indexes?: number[]) {
    if (!indexes) {
        return;
    }

    for (let i = 0; i < indexes.length; i++) {
        const index = indexes[i];
        //    ~~~~~ 'index' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.(7022)
        if (index in items) {}
    }
}

Playground link

Again we can get rid of the error a small adjustment. Any of those work:

  • Make indexes not undefined (remove the ? from the parameter)
  • Add a type annotation to index: const index: number = ...
  • Remove the line if (index in items) {}

@RyanCavanaugh RyanCavanaugh added the Rescheduled This issue was previously scheduled to an earlier milestone label Dec 15, 2021
@frigus02
Copy link
Contributor Author

We're currently upgrading to TypeScript 4.7 (beta) and that caused another issue that looks very similar to this one.

interface Method {
  httpMethod: string;
}

interface Resource {
  methods?: {[index: string]: Method};
}

function extract(resource: Resource): void {
  const store: Record<string, unknown> = {};
  if (resource.methods) {
    for (const methodName of Object.keys(resource.methods)) {
      const methodSpec = resource.methods[methodName];
      //    ^^^^^^^^^^  'methodSpec' implicitly has type 'any' because it does not have a type annotation and is referenced directly or indirectly in its own initializer.(7022)
      const verb = methodSpec.httpMethod.toLowerCase();
      store[verb] = {};
    }
  }
}

Playground (4.6.2) --> all fine, no error

Playground (nightly, 4.7.0-dev.20220422) --> error as included in the snippet above

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs Investigation This issue needs a team member to investigate its status. Rescheduled This issue was previously scheduled to an earlier milestone
Projects
None yet
Development

No branches or pull requests

4 participants