Rins
Rins

Reputation: 2191

ESLint - Configuring "no-unused-vars" for TypeScript

I use ESLint in all of my TypeScript projects with the following settings:

  "extends": ["airbnb", "prettier", 'plugin:vue/recommended'],
  "plugins": ["prettier"],
  "parserOptions": {
  "parser": "@typescript-eslint/parser",
  "ecmaVersion": 2018,
  "sourceType": "module"
  },

However, one of ESLint's most useful rules, https://eslint.org/docs/rules/no-unused-vars, seems to be very poorly configured for TypeScript projects. For example, when I export an enum, the rule warns me that the enum isn't in use in the file where it is declared:

export enum Foo {
   Bar,
}

Similarly, when I import an interface or class to be used as a type, 'no-unused-vars' will complain again on the the line of the actual import:

In Foo.ts

export interface Foo {
   bar: string;
}

In bar.ts

import { Foo } from './Foo'
const bar: Foo = { bar: 'Hello' };

Is there any way to configure the no-unused-vars rule to take these two cases into account? I'm not a fan of disabling the rule, as it is one of the most helpful rules in my entire ruleset outside of these cases.

I've already downgraded the rule to only give a warning instead of an error, but having all my documents filled with warnings still kind of defeats the purpose of using esLint.

Filling my all my documents with //eslint-disable-line as suggested here also seems like a bad solution.

Upvotes: 189

Views: 278854

Answers (15)

Awshaf Ishtiaque
Awshaf Ishtiaque

Reputation: 961

I had the same issue in JS, and the problem was that I was using pluginJs.configs.recommended AFTER my custom rules.

So the custom rule was overwritten by the recommended rules ( in the eslint.config.mjs ).

Simply having the recommended rule and then overwriting it with the custom rule "no-unused-vars": "off", fixed the problem.

// eslint.config.mjs

export default [
  pluginJs.configs.recommended, // <--here
  {
   ......
    rules: {
      "no-unused-vars": "off", // <--here
    .....
  },
];

Upvotes: 1

Greg Wozniak
Greg Wozniak

Reputation: 7272

Might be helpful for those who struggle with function parameters to turn it off.

If you still see the error, even if your .eslintrc is configured as:

'@typescript-eslint/no-unused-vars': 'off'

make sure you set:

"noUnusedParameters": false

in your tsconfig.json.

Upvotes: 1

zrna
zrna

Reputation: 594

For folks whose configuration is working in Project A, and not working in Project B, and the config is identical → here are some of the solutions that might help:

  • reopen your IDE
  • disable and enable the ESLint extension

Works for me every time.

Upvotes: 0

David Ko
David Ko

Reputation: 187

My problem was in using the same name for exported class function component and type in the same file. For some reason eslint didn't provide any information about that, but was constantly complaining about exported component was not used... Hope it helps somebody. Below is my code:

type Component = {
  readonly prop1: string;
  readonly prop2: string;

 export const Component = (
  props: Component
): ReactElement => {
  return (<p>Component</p>)
}

Which was causing warn for exported Component function. Renaming the Component type to something unique like ComponentProps fixed the problem:

type ComponentProps = {
  readonly prop1: string;
  readonly prop2: string;

 export const Component = (
  props: ComponentProps
): ReactElement => {
  return (<p>Component</p>)
}

Upvotes: 0

Viktor M
Viktor M

Reputation: 452

In my opinion, turning the rule off is a bit dangerous for projects where typescript and javascript are used simultaneously.

The solution is to define "overrides" on root level in .eslintrc.json file:

  "overrides": [
    {
      "files": ["*.ts"],
      "rules": {
        "no-unused-vars": "off"
      }
    }
  ],

Upvotes: 5

jaibatrik
jaibatrik

Reputation: 7543

I think the use of "plugin:@typescript-eslint/eslint-recommended" introduces bunch of unwanted rules. One is probably better off using "@typescript-eslint/no-unused-vars" ESLint rule instead.

{
  "parser": "@typescript-eslint/parser",
  "plugins": [
    "@typescript-eslint",
  ],
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended",
  ],
  "rules": {
    "no-unused-vars": "off",
    "@typescript-eslint/no-unused-vars": ["error"]
  }
}

Note: be sure to restart your server after making the above change.

Reference - https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-unused-vars.md

Upvotes: 266

user19357257
user19357257

Reputation: 1

I use this configuration and it works normally

{
  "env": {
    "browser": true,
    "es2021": true,
    "node": true,
    "jest": true
  },
  "extends": ["airbnb-base", "prettier"],
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "ecmaVersion": "latest",
    "sourceType": "module"
  },
  "plugins": ["@typescript-eslint", "jest"],
  "rules": {
    "import/extensions": "off",
    "@typescript-eslint/no-unused-vars": ["error"]
  },
  "settings": {
    "import/resolver": {
      "node": {
        "extensions": [".js", ".jsx", ".ts", ".tsx"]
      }
    }
  }
}

Upvotes: -1

Andrew E
Andrew E

Reputation: 8337

For anyone looking to get no-unused-vars working properly in TypeScript when using YAML configuration, e.g. .eslintrc.yaml, it looks like this:

rules:

  "@typescript-eslint/no-unused-vars":
  - warn
  - argsIgnorePattern: "^_"                # <-- NOTE!
    varsIgnorePattern: "^_"
    caughtErrorsIgnorePattern: "^_"

  no-unused-vars: # disabled but see typescript-eslint/no-unused-vars
  - off
  ...

Upvotes: 11

chavy
chavy

Reputation: 1068

Also for me works rule /eslint no-unused-vars: ["error", { "varsIgnorePattern": "[iI]gnored" }]/
You can add it like this in your .eslintrc.json file (this one is for ignoring all Strings which start with Capital letter)

    "rules": {
        "no-unused-vars": [
          "error",
          {
            "varsIgnorePattern": "^[A-Z]"
          }
        ],
    }

For more information, and properties you can check this link.

Upvotes: 3

supNate
supNate

Reputation: 430

Upgrading @typescript-eslint/eslint-plugin and @typescript-eslint/parser from 3.x to the latest 4.x resolved the issue for me.

Upvotes: 5

Dipak Telangre
Dipak Telangre

Reputation: 1993

After couple of year still getting the same error. It's frustrate to try and check why it's not working. After trying lot of possible configuration here is the finally working for me. Incase someone had difficulties like me !

eslintrc.js

module.exports = {
    env: {
        browser: true,
        node: true,
    },
    parser: "@typescript-eslint/parser",
    extends: [
        "eslint:recommended",
        "plugin:@typescript-eslint/eslint-recommended",
        "prettier",
        "plugin:prettier/recommended",
        "plugin:@typescript-eslint/recommended",
    ],
    parserOptions: {
        ecmaVersion: 2020, // Allows for the parsing of modern ECMAScript features
        project: "tsconfig.eslint.json",
        tsconfigRootDir: __dirname,
        sourceType: "module", // Allows for the use of imports
    },
    plugins: ["@typescript-eslint", "@typescript-eslint/tslint", "import", "unused-imports"],

    rules: {
        "@typescript-eslint/no-unused-vars": "off",
        "@typescript-eslint/no-unused-vars-experimental": "error",
        "no-unused-vars": "off",
        "import/order": "error",
        "no-console": ["warn", { allow: ["warn", "error"] }],
        eqeqeq: ["error", "always"],
        "no-else-return": "error",
    },
    settings: {
        "import/resolver": {
            node: {
                extensions: [".js", ".jsx", ".ts", ".tsx"],
                moduleDirectory: ["node_modules", "src/"],
            },
        },
    },
};

Upvotes: -1

ghiscoding
ghiscoding

Reputation: 13214

I got lot of false errors with latest TypeScript/ES-Lint versions and I found that they came up with an experimental rule to fix the no-unused-vars which is broken and with the experimental rule @typescript-eslint/no-unused-vars-experimental it finally works as I expect it to.

Prior to the change on my side, I had multiple false errors when using interfaces/types saying that these vars were unused (which of course they'll never be used since they're not variables but rather interfaces/types)... and in case you're curious about the code itself, here is the PR adding this experimental rule which is how I found the rule.

Here's a subset of my updated .eslintrc file

{
  "parser": "@typescript-eslint/parser",
  "extends": [
    "plugin:@typescript-eslint/recommended"
  ],
  "rules": {
    "@typescript-eslint/no-unused-vars": "off",
    "@typescript-eslint/no-unused-vars-experimental": "error",
    "no-unused-vars": "off"
  }
}

and I'm now finally back to normal :)

EDIT (Jan. 2021)

As mentioned by Brad (a maintainer of the project) in the comment below, this is (was) a temporary solution and is now deprecated. From his comment (below), we can now use directly @typescript-eslint/no-unused-vars for the same intended behavior. Thanks to Brad for the info. I can also confirm that switching back to @typescript-eslint/no-unused-vars now works for me (I updated my code and it's all good now).

This is not the way to go, and you should avoid it. @typescript-eslint/no-unused-vars-experimental is deprecated, and will be removed in the next major. Update to the latest version of the tooling and just use @typescript-eslint/no-unused-vars. Source: I am the maintainer of the project.

UPDATED ANSWER since Jan. 2021

So here's the latest update of my .eslintrc file which works for me :)

{
  "parser": "@typescript-eslint/parser",
  "extends": [
    "plugin:@typescript-eslint/recommended"
  ],
  "rules": {
    "@typescript-eslint/no-unused-vars": "error",
    "no-unused-vars": "off"
  }
}

Upvotes: 79

thisismydesign
thisismydesign

Reputation: 25152

My issue was with using decorators and wanting to have a variable with an appropriate name for clarity, for example:

@OneToMany((type) => Employee) instead of @OneToMany(() => Employee)

The usual solution for TypeScript is to prefix with an underscore:

@OneToMany((_type) => Employee)

And it's possible to make ESLint accept the same:

.eslintrc.js

module.exports = {
  ...
  rules: {
    '@typescript-eslint/no-unused-vars': ['warn', { 'argsIgnorePattern': '^_' }]
    ....
  },
};

Upvotes: 29

dolios
dolios

Reputation: 2011

It's a bit buried in the documentation, but if you add some things to the 'extends' property, you can use both the rules recommended by ESLint like no-unused-vars, and have it actually work in Typescript. Like so:

"extends": [
        "eslint:recommended",
        "plugin:@typescript-eslint/eslint-recommended",
        "plugin:@typescript-eslint/recommended"
    ],

@typescript-eslint/recommended seems to be the thing that allows eslint:recommended to deal with Typescript constructs effectively. Not sure how it would affect your other extensions though.

Upvotes: 173

Jay Kariesch
Jay Kariesch

Reputation: 1482

You have parser nested inside of parserOptions. It should be a sibling, like this:

"parser": "@typescript-eslint/parser",
"parserOptions": {
    "ecmaVersion": 2018,
    "sourceType": "module"
},

As for no-unused-vars, I'm afraid this is an ongoing bug with @typescript-eslint: https://github.com/typescript-eslint/typescript-eslint/issues/363

Upvotes: 5

Related Questions