52

So, I have this piece of code in .ts file:

import {MicroEventInterface} from '../Interfaces';

export default class MicroEvent implements MicroEventInterface {

// code

And ESLint throws this error:

error

I have this config for TypeScript in ESLint:

typescript: {
    extends: [
        'plugin:@private/private/react' // private rep with React config
    ],
    parser: '@typescript-eslint/parser',
    plugins: [
        '@typescript-eslint',
        'import'
    ],
    settings: {
        'import/resolver': {
            'node': {
                'extensions': [
                    '.js',
                    '.jsx',
                    '.ts',
                    '.tsx'
                ],
                'moduleDirectory': [
                    'node_modules/',
                    'src/'
                ]
            }
        },
        react: {
            createClass: 'createClass',
            pragma: 'React',
            version: '0.14.9'
        }
    }
}

So, everything seems like fine, but I can't conquer this error.

Any suggestions?

Thanks!

UPD:

Looks like if I console.log( --- , MicroEventInterface); error disappears. I think, ESLint does not treat implements as actual usage.

Brad Zacher
  • 2,915
  • 18
  • 31
Nikita Shchypyplov
  • 1,090
  • 1
  • 9
  • 18
  • ESLint generally throws such error when the imported modules have not been used in the defining scope. Basically, it wants to say, "Why do you even import something when you don't need it". – Vikas Mishra Apr 23 '19 at 08:45
  • 3
    @VikasMishra yep, I understand that. But I am actually using it with 'implements' command. – Nikita Shchypyplov Apr 23 '19 at 08:46
  • Implementing something doesn't mean you are using it. Implement just dictates that it conforms (might use) specific modules if required. – Vikas Mishra Apr 23 '19 at 08:48
  • 1
    @VikasMishra So, how then may I fix this issue? Should I place my interfaces in the same file with component? Does this BP? – Nikita Shchypyplov Apr 23 '19 at 08:52
  • Add this to ESLint config file { "rules": { "no-unused-vars": [2, {"vars": "local", "args": "after-used"}] } } – Vikas Mishra Apr 23 '19 at 08:56
  • @VikasMishra Nope, does not work me. Still see this error – Nikita Shchypyplov Apr 23 '19 at 09:19
  • Do not use ESLint. Prefer TSLint. – Paleo Apr 23 '19 at 09:19
  • 2
    @Paleo using TSLint over ESLint isn't a valid option as of 2019, as the TSLint project is being deprecated in favor of using ESLint with TypeScript: https://github.com/palantir/tslint/issues/4534 – John T Aug 01 '19 at 19:29
  • Same issue when importing an interface and use it as a variable or return type. e.g. Reacts FunctionComponent. Is there a solution that works? – Mario Eis Apr 23 '20 at 15:11

5 Answers5

69

Source: I am the maintainer of the typescript-eslint project.

The latest version of the @typescript-eslint tooling now has full support for scope analysis.

So the steps to fix this are now:

  • update your versions to at least v4.9.1 of @typescript-eslint/parser and @typescript-eslint/eslint-plugin
  • update your ESLint version to at least v6.0.0
  • update your config to use @typescript-eslint/no-unused-vars

Restart your IDE and you should now see the correct lint errors.

Brad Zacher
  • 2,915
  • 18
  • 31
  • what if ESLint version is ^6.6.0? That is what is expected when we create project with create react app. – Stefan Sep 30 '20 at 12:02
  • CRA is in the process of updating to a newer version of eslint and plugins. You can try their upcoming v4 release using their `next` tag on NPM. – Brad Zacher Sep 30 '20 at 15:09
  • 1
    @BradZacher - can you please detail the `update your config to use @typescript-eslint/no-unused-vars` bit? Should it look like this? `"rules": { "import/first": "off", "no-unused-vars": "off", "@typescript-eslint/no-unused-vars": ["error"] }` – CanuckT Nov 29 '20 at 09:30
  • 1
    Try the docs for more info: https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-unused-vars.md – Brad Zacher Nov 29 '20 at 20:38
  • 6
    On `@typescript-eslint/parser+plugin` v4.14 and `eslint` v7.18, this still occurs for implemented interfaces. – Joep Beusenberg Jan 30 '21 at 18:37
  • The github issue tracker is a much better place to discuss bugs. There you'll find a relevant issue that has been addressed and see the fix is due out Monday. – Brad Zacher Jan 30 '21 at 18:38
  • 1
    @JoepBeusenberg yeah same here. Did you figure out a way to resolve the issue? – Hansel May 06 '21 at 02:36
  • Version `4.9.1`? – JayCodist Sep 21 '21 at 23:46
  • 1
    @JayCodist - that was the first version with this feature. But it's now some 12 months old. Consider using the latest version published to NPM. – Brad Zacher Sep 21 '21 at 23:49
  • Even with this adapted, it still complains about a function's args, even when those come from implementing an interface, meaning the fact they're unused is irrelevant. – Nyerguds Feb 25 '22 at 15:42
  • @Nyerguds check the documentation. There are options you can use to customise this behaviour. – Brad Zacher Feb 26 '22 at 16:08
  • @BradZacher But why are they options? These things should automatically be excluded when they come from interfaces. – Nyerguds Feb 27 '22 at 19:07
  • @Nyerguds they are options because not everyone wants unused code in their codebase. Most codebases don't design APIs with unnecessary parameters. So you can configure it as you wish based on the code you have. You can configure the ignore pattern to your liking so you can flag intentionally unused variables as desired. Config to how your codebase works. – Brad Zacher Mar 01 '22 at 08:09
  • @BradZacher happening now in v6 – Lance Jul 11 '23 at 09:10
  • @Lance what is happening now....? – Brad Zacher Jul 12 '23 at 11:23
  • the error from the question "ESLint throws 'no-unused-vars' for TypeScript interface" only get the error on v6 not v5 – Lance Jul 19 '23 at 08:08
  • It's likely a config error in your project. However Stackoverflow comments are NOT a good way to attempt to have discussions about problems. There is a lot of context I need to be able to help you. Consider filing an issue on github so you can provide the information and I can help you find the solution. Help me to help you. – Brad Zacher Jul 20 '23 at 09:11
23

add this to Eslint rules

"rules": {
  "@typescript-eslint/no-unused-vars": [
    2,
    {
      "args": "none"
    }
  ]
}
Matt Coady
  • 3,418
  • 5
  • 38
  • 63
Artem Bochkarev
  • 1,242
  • 13
  • 23
  • 1
    https://github.com/eslint/eslint#configuration and https://eslint.org/docs/rules/no-unused-vars#args for additional info. Also 2 could be replaced with "error" – Rubén Pozo Jul 11 '20 at 12:20
20

Use @typescript-eslint/no-unused-vars-experimental and turn off @typescript-eslint/no-unused-vars.

The issue is resolved in the latter version (experimental).

Sample config:

// .eslintrc
{
  ...
  "rules": {
    "@typescript-eslint/no-unused-vars": "off",
    "@typescript-eslint/no-unused-vars-experimental": "error"
  }
  ...
}

1

Using the varsIgnorePattern Rule

To solve this issue in a pure TypeScript project, I added the following rule to my eslint config file (.eslintrc.json). For this particular solution to work, you must follow the convention that interface names begin with an upper case "I".

Incidentally, other artifacts (namely classes) with the first letter of their name being an upper case "I" will also be ignored when considering whether they are used.

Eslint

...
    "rules": {
        ... other rules omitted ...,
        "no-unused-vars": [
            "warn",
            { 
                "vars": "all",
                "varsIgnorePattern": "[I]\\w+"
            }
        ]
    }
...

For more information on this rule, see the documentation.

Jason
  • 2,382
  • 1
  • 16
  • 29
  • If you don't like the solution, please leave a comment as to why. Just because you don't like the solution, doesn't make it invalid. I did clearly state caveats. – Jason Jun 20 '22 at 19:52
1

Add the following rule to your .eslintrc.json file

{
  rules: {
    "@typescript-eslint/no-unused-vars": "warn",
  }
}
Ray
  • 238
  • 5
  • 8