Setting up ESLint for TypeScript to enforce the "no-unused-vars" rule

In all my TypeScript projects, I utilize ESLint with specific settings in place:

  "extends": ["airbnb", "prettier", 'plugin:vue/recommended'],
  "plugins": ["prettier"],
  "parserOptions": {
  "parser": "@typescript-eslint/parser",
  "ecmaVersion": 2018,
  "sourceType": "module"
  },
  • Along with a set of custom rules, I've also integrated the following dependencies for TypeScript support:

      "@typescript-eslint/eslint-plugin": "^1.7.0",
      "@typescript-eslint/parser": "^1.7.0",
    

However, I have encountered a hurdle with one of ESLint's most valuable rules, https://eslint.org/docs/rules/no-unused-vars, specifically when it comes to TypeScript projects. For instance, the rule triggers warnings when I export an enum, stating that the enum is not being used within the same file:

export enum Foo {
   Bar,
}

Similarly, when importing an interface or class to be used as a type, 'no-unused-vars' also prompts warnings at the import statement:

In Foo.ts

export interface Foo {
   bar: string;
}

In bar.ts

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

Is there a way to configure the no-unused-vars rule to address these scenarios? I prefer not to disable the rule, as it is generally beneficial in my ruleset apart from these instances.

Even after downgrading the rule to a warning instead of an error, having warnings scattered throughout my documents diminishes the purpose of using ESLint.

Adding //eslint-disable-line to all my documents as recommended here does not seem like an ideal solution either.

Answer №1

In my opinion, utilizing the

"@typescript-eslint/no-unused-vars"
ESLint rule is a more efficient choice compared to using
"plugin:@typescript-eslint/eslint-recommended"
which may introduce unnecessary rules.

{
  "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"]
  }
}

Remember to restart your server after implementing the change mentioned above.

For more information, check out the following reference - https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-unused-vars.md

Answer №2

If you dive into the documentation, you'll discover a valuable approach to leveraging both ESLint's recommended rules, such as no-unused-vars, and making them compatible with Typescript. Simply add the following to the 'extends' property:

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

The inclusion of @typescript-eslint/recommended seems to be the key in enabling eslint:recommended to effectively handle Typescript syntax. However, the impact on other extensions is uncertain.

Answer №3

Encountering numerous false errors with the latest versions of TypeScript/ESLint, I discovered an experimental rule that addresses the issue of no-unused-vars. This rule,

@typescript-eslint/no-unused-vars-experimental
, finally resolves the errors as expected.

Prior to implementing this change, I faced misleading errors related to unused interfaces/types, which are not technically variables. These errors were misleading since these interfaces/types inherently remain unused. For those interested, the PR introducing this experimental rule helped me identify the solution.

Below is an excerpt from my revised .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"
  }
}

With this adjustment, everything is now functioning normally again :)

UPDATE (January 2021)

An update shared by Brad, a project maintainer, in the comment section below has clarified that the temporary solution involving

@typescript-eslint/no-unused-vars-experimental
is deprecated. Users should now directly utilize
@typescript-eslint/no-unused-vars
for the intended behavior. This information was greatly appreciated, and I have successfully transitioned back to
@typescript-eslint/no-unused-vars
in my codebase.

It is advisable to avoid using

@typescript-eslint/no-unused-vars-experimental
as it is now deprecated and will be phased out in the next major update. To ensure compatibility, upgrade to the latest tooling version and make use of
@typescript-eslint/no-unused-vars
. Source: Brad, the project maintainer.

UPDATED RESPONSE as of January 2021

Here is the up-to-date version of my .eslintrc file that is currently working as intended :)

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

Answer №4

When working with decorators, I ran into an issue where I wanted to use a variable name that made the code clearer, like this:

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

To solve this in TypeScript, the common practice is to prefix with an underscore:

@OneToMany((_type) => Employee)

There is a way to configure ESLint to allow this as well:

.eslintrc.js

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

Answer №5

If you're trying to configure no-unused-vars in TypeScript with a YAML file, such as .eslintrc.yaml, the setup should be like this:

rules:

  "@typescript-eslint/no-unused-vars":
  - warn
  - argsIgnorePattern: "^_"                # Remind: this line!
    varsIgnorePattern: "^_"
    caughtErrorsIgnorePattern: "^_"

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

Answer №6

The parser element is currently nested within the parserOptions element. It should be a sibling element, presented like this:

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

Concerning the no-unused-vars issue, unfortunately, it seems to be a persistent bug related to @typescript-eslint: https://github.com/typescript-eslint/typescript-eslint/issues/363

Answer №7

By updating `@typescript-eslint/eslint-plugin` and `@typescript-eslint/parser` from version 3.x to the most recent 4.x, I was able to successfully resolve the problem.

Answer №8

In my view, disabling the rule can be risky when working on projects that involve both typescript and javascript.

A practical solution would be to set "overrides" at the root level in the .eslintrc.json file:

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

Answer №9

Another rule that has worked well for me is /eslint no-unused-vars: ["error", { "varsIgnorePattern": "[iI]gnored" }]/
You can easily add this rule to your .eslintrc.json file. For example, this particular rule ignores all Strings that start with a Capital letter.

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

For further details and additional properties, you may refer to this link.

Answer №10

For years, I struggled with the same error, endlessly trying to figure out why it wasn't working. After experimenting with various configurations, I finally found a solution that worked for me. Hopefully, this helps someone else facing similar difficulties!

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/"],
            },
        },
    },
};

Answer №11

I have implemented this specific configuration and it is functioning as expected.

{
  "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"]
      }
    }
  }
}

Answer №12

After encountering an issue in my code where I inadvertently used the same name for an exported class function component and a type within the same file, I realized that eslint did not flag this as an error. Instead, it kept complaining about the fact that the exported component was not being used. I hope my experience can help someone else facing a similar issue. Below is the snippet of code that caused the problem:

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

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

This led to a warning for the exported Component function. To resolve this issue, I simply renamed the Component type to something unique, like ComponentProps:

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

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

Answer №13

If your setup works perfectly in Project A but not in Project B despite identical configurations, here are a couple of potential fixes you can try out:

  • Close and reopen your Integrated Development Environment
  • Try disabling and re-enabling the ESLint extension

This has always been a reliable solution for me.

Answer №14

For individuals finding it difficult with function parameters, here is a suggestion to resolve the issue.

If the error persists despite having your .eslintrc set to:

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

ensure that you also include:

"noUnusedParameters": false

in your tsconfig.json.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Exploring the Power of Node.JS in Asynchronous Communication

Hey there, I'm not here to talk about async/await or asynchronous programming - I've got that covered. What I really want to know is if it's possible to do something specific within a Node.js Express service. The Situation I've built ...

Mapping two objects of the same shape to each other recursively using TypeScript

I receive regular data from a specific source. This data consists of nested objects containing numerical values. For example: { a: 1, b: { c: 2, d: 3.1, }, } My objective is to organize this data into multiple TimeSeries objects of the same struct ...

Struggling to modify a string within my React component when the state is updated

Having a string representing my file name passed to the react-csv CSVLink<> component, I initially define it as "my-data.csv". When trying to update it with data from an axios request, I realize I may not fully understand how these react components w ...

The type 'Item' cannot be assigned to type 'ReactNode'

I'm having trouble understanding the meaning of this error. I've created a Type for an array of items where each item is a string. Interestingly, when I enclose the listItem within an empty fragment, the error disappears. Is there something I&ap ...

VS Code fails to identify Typescript internal modules

I am currently facing issues with separating my TypeScript classes into distinct files using internal modules. Unfortunately, the main.ts file is not loading or recognizing the sub-modules. main.ts /// <reference path="Car.ts" /> module Vehicles { ...

I'm encountering an issue with my Angular 8 function not running, and I'm unsure of the reason behind it as there are no error messages appearing

Here is a function that I have: Join(movementId: string, movement: Movement, userId: string) { let fetchedUserId: string; let userList = []; fetchedUserId = userId; userList = movement.userList; userList.push(fetchedUserId); movement.userList ...

What is the method for defining a mandatory incoming property in an Angular2 component?

In my current project, I am developing a shared grid component using Angular2 that requires an id property. export class GridComponent { @Input() public id: string; } I'm looking for a way to make the id property mandatory. Can you help me with ...

What is the best way to access a property within a typescript object?

I'm working with the following code snippet: handleSubmit() { let search = new ProductSearch(); search = this.profileForm.value; console.log(search); console.log(search.code); } When I run the console.log(search) line, it outputs: ...

Having difficulty with installing the ttf-loader for React with Typescript

Currently, I am working on a project using React with TypeScript and trying to incorporate the font feature in react-pdf/renderer. The font has been successfully imported and registered as shown below: import { Text, View, StyleSheet, Font } from "@re ...

What is the process for turning off a TypeScript rule for a single line of code?

Dealing with Summernote as a jQuery plugin has been a bit of a struggle for me. I'm trying to modify the object without needing type definitions, but TypeScript keeps throwing errors my way. Even after attempting to delete certain keys, I still get th ...

Is there a workaround for utilizing reducer dispatch outside of a React component without relying on the store?

Recently, I implemented a reducer in my project that involves using react, typescript and nextJS. I am wondering if there is a method to trigger the reducer outside of a react component, such as from an API service. While searching for solutions, most re ...

Rule in Eslint for Typescript that enforces explicit typing and prohibits the use of implicit "any

Starting a fresh typescript project with eslint, I'm facing an issue in setting up eslint rules for the tsc command to run smoothly without errors. Specifically, I'm encountering difficulty with the "noImplicitAny" rule defined in tsconfig.json, ...

Troubleshooting TypeScript errors related to ReactNode post-upgrade to Create React App v5

Since upgrading to Create React App version 5, I've been encountering errors like the one below: TS2786: 'OutsideClickHandler' cannot be used as a JSX component. Its instance type 'OutsideClickHandler' is not a valid JSX element. ...

What could be causing the elements in my array to appear as undefined?

https://i.stack.imgur.com/ze1tx.png I'm stuck trying to understand why I can't extract data from the array. const usedPlatformLog: Date[] = [] users.forEach(el => { usedPlatformLog.push(el.lastUsed) }) console.log(usedPlatformLog) // disp ...

How to disable typescript eslint notifications in the terminal for .js and .jsx files within a create-react-app project using VS Code

I'm currently in the process of transitioning from JavaScript to TypeScript within my create-react-app project. I am facing an issue where new ESLint TypeScript warnings are being flagged for my old .js and .jsx files, which is something I want to avo ...

Retrieving data from a nested JSON array using AngularJS

I am struggling to navigate the intricate nested tree view of child items within a JSON array. I have been grappling with this challenge for days, trying to figure out how to access multiple children from the complex JSON structure. Can someone provide g ...

The functionality of connect-flash in Express JS is compromised when used in conjunction with express-mysql-session

I am facing a unique issue in my project. I have identified the source of the problem but I am struggling to find a solution. My project utilizes various modules such as cookie-parser, express-mysql-session, express-session, connect-flash, passport and m ...

Phaser3 encountering issues while loading files from Multiatlas

Attempting to utilize the multiatlas functionality in Phaser alongside TexturePacker. Encountering this issue: VM32201:1 GET http://localhost:8080/bg-sd.json 404 (Not Found) Texture.js:250 Texture.frame missing: 1/1.png The JSON file can actually be fou ...

Tips for managing errors when using the mergeMap feature in Angular's Typeahead search

Currently working on implementing Typeahead search functionality using API data. When we input valid data, the autosuggestions work correctly. However, if we input invalid data, we receive an error message. The issue arises when trying to input valid dat ...

Utilizing Angular RXJS to generate an array consisting of three different observable streams

I am trying to use three different streams to create an array of each one. For example: [homePage, mainNavigation, loan_originators] However, currently only mainNavigation is being returned. const homePage = this.flamelinkService.getData('homePage ...