eslint-plugin-import: import/no-unresolved errors for .d.ts files since 2.25

Environment

Node: 16.11.1 ESLint: 7.32.0 Operating System: Linux

What happened?

We tried to update eslint-plugin-import in https://github.com/hedgedoc/react-client from 2.24.2 to 2.25.2 but eslint fails now. It can’t resolve paths to .d.ts files anymore.

What did I expect?

No breaking changes in behaviour since it isn’t a major release.

Additional Information

Feel free to take a look at our CI log. https://github.com/hedgedoc/react-client/runs/3915016791?check_suite_focus=true

Thanks for your help

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 16
  • Comments: 29 (12 by maintainers)

Commits related to this issue

Most upvoted comments

Just tested: One way to make this work without renaming all .d.ts files to .ts is to replace the import with a type import.

import { bar } from "./bar"; becomes import type { bar } from "./bar";

A bit annoying if you have many many .d.ts files like image

Oh no! I became the person in this xkcd 🙈

https://xkcd.com/1172/

Adding

"@typescript-eslint/consistent-type-imports": [
        "error",
        {
          "prefer": "type-imports",
          "disallowTypeAnnotations": false
        }
      ]

to my eslint config helped a lot, because then eslint was able to autofix this.

But still: This breaking changes in patch releases are bad 😕

Even if this is a bug fix, it’s still a breaking change in behaviour and shouldn’t be present in a patch release.

In a pure typescript environment it’s normal to use .d.ts files that just provide types or interfaces but no functions. E.g. if you want to share types between multiple ts files.

This was introduced by 4d15e268b694e9e9946ea16d9e1b94de1b850d7c (#2220). Cc @jabiko.

Minimal reproduction:

// foo.ts
import { bar } from "./bar";
console.log(bar);
// bar.d.ts
export const bar: string;
// .eslintrc.json
{
  "plugins": ["@typescript-eslint", "import"],
  "parser": "@typescript-eslint/parser",
  "extends": "plugin:import/typescript",
  "rules": {
    "import/no-unresolved": "error"
  }
}
$ npm i -D @typescript-eslint/eslint-plugin@5.0.0 @typescript-eslint/parser@5.0.0 eslint@7.32.0 eslint-plugin-import@2.25.2 typescript@4.4.4
$ npx eslint foo.ts
 
/home/anders/zulip/test/eslint-import-bug/foo.ts
  2:21  error  Unable to resolve path to module './bar'  import/no-unresolved

✖ 1 problem (1 error, 0 warnings)

@mrdrogdrog it’s not normal to have a .d.ts file and no corresponding .js file to be imported.

Yes, breaking changes in patch releases are bad, but every single bug fix is a breaking change if someone’s relying on the bug.

I see what you mean tho - in this case, you’re importing a type, but you weren’t using the preferred import type syntax for it, so it shouldn’t have warned but did.

I think the issue is that you’re not using the TS resolver (but neither is https://github.com/import-js/eslint-plugin-import/blob/main/config/typescript.js#L18-L22).

If you add the TS resolver - above node - does it work?

I get also problems with .d.ts for import/extensions now. I believe it belongs to the problems described here, so I don’ create a new bug for it.

I’m using the config 'import/extensions': ['error', 'always', { pattern: { js: 'never', ts: 'never' }, ignorePackages: true }].

If I have a file foo.d.ts without a corresponding .js file, I’m getting now errors for import like import type { ... } from './foo';.

@mrdrogdrog it’s not normal to have a .d.ts file and no corresponding .js file to be imported.

That is wrong in my opinion. e.g. when I want to describe the expected messages of a communication I add them to an own file. Or if I describe an option param of a method which is used in different files (because it is passed through or so) I want to have it also described in an own options.d.s file.

So it could be, that the most are not doing this but I want to be able to do it like I think it is good. Can we provide an option to that rules to get the old behavior again?

But for now I have to disable all the rules 😦

edit:

I see what you mean tho - in this case, you’re importing a type, but you weren’t using the preferred import type syntax for it, so it shouldn’t have warned but did.

the import type is not possible always: when importing a const enum to use a value of it, I can not add the type

cc @jablko, it’d be great to roll forward with a fix so we don’t have to revert #2220.

Thanks! I’ve opened #2270 aimed at the issue reported by @Ulrikop, with import/extensions rule and type-only imports.

OK, to sum up:

When using the typescript resolver, and importing a type, or an enum, from a .d.ts file - whether there’s a corresponding .js file or not, and whether using import type or not - it should resolve and the linter should not warn.

When not using the typescript resolver, and using typescript, your config is unsupported.

cc @jablko, it’d be great to roll forward with a fix so we don’t have to revert #2220.

For me this topic is done. I changed our code to use import type which is more correct. 🤷

I don’t see the behavior of eslint as a bug anymore.

Thank you for your help ♥️

Yes, I copied the changes of the PR #2270 into my node_modules directory.

The following previously mentioned issue is resolved with the change:

If I have a file foo.d.ts without a corresponding .js file, I’m getting now errors for import like import type { ... } from './foo';.

But since the fix on the PR only changes that an import type is not checked with the Missing file extension error, the problem remains when importing without the type keyword (like my example with a const enum).

I’ve the same issue as @Ulrikop . I downgraded to eslint-plugin-import@2.24.2