What is the best way to set up the parser and plugins using ESLint's updated flat configuration?

How can ESLint be configured using the new "flat config" system (specifically with the eslint.config.js file) to work seamlessly with both @typescript-eslint/eslint-plugin and /parser?

I have been struggling to make ESLint's new configuration system play well with plugins, and conversely, I am unable to get plugins to function smoothly with flat config.

When it comes to linting TypeScript code with ESLint, incorporating the two essential plugins listed below is crucial. These plugins define rules that enable ESLint to effectively lint TypeScript code bases:

My current configuration file resembles the example provided below. However, please note that this is just my latest attempt as I have experimented with various approaches:

import eslintPlugin from '@typescript-eslint/eslint-plugin'

export default [
  {
    files: ["src/**/*.ts", "src/main.cts", "src/main.mts"],
    ignores: ["**/*.d.*", "**/*.map.*", "**/*.js", "**/*.mjs", "**/*.cjs"],
    plugins: { eslintPlugin },

    languageOptions: {
      ecmaVersion: "latest",
      sourceType: "module",
      parser: "eslintPlugin/parser",
    },

    rules: {
      semi: "error",
      quotes: ["error", "single"],
      indent: [
        "error",
        2,
        {
          SwitchCase: 1,
          VariableDeclarator: "first",
          ImportDeclaration: "first",
          ArrayExpression: "first",
          ObjectExpression: "first",
          CallExpression: { arguments: "first" },
          FunctionDeclaration: { body: 1, parameters: 4 },
          FunctionExpression: { body: 1, parameters: 4 },
        },
      ],
    },
  },

];

In addition, I utilize the TypeScript ESLint Language Service plugin. I prefer not to have any overlap in error reporting between TypeScript and ESLint; therefore, I do not use any ESLint extension. Instead, I have integrated a build system that conducts linting on my project as I work, and any errors identified by ESLint are presented through the TSC compiler.

However, the issue persists – I am still encountering difficulties getting the language service plugin to cooperate with flat config.

Answer №1

In my setup with TypeScript and flat configuration, I have identified some key elements in the configuration:

import ts from '@typescript-eslint/eslint-plugin';
import tsParser from '@typescript-eslint/parser';
import functional from 'eslint-plugin-functional';
import imprt from 'eslint-plugin-import'; // 'import' is ambiguous & prettier has trouble

...

    languageOptions: {
      parser: tsParser,
      parserOptions: {
        ecmaFeatures: { modules: true },
        ecmaVersion: 'latest',
        project: './tsconfig.json',
      },
    },
    plugins: {
      functional,
      import: imprt,
      '@typescript-eslint': ts,
      ts,
    },

...

    rules: {
      ...ts.configs['eslint-recommended'].rules,
      ...ts.configs['recommended'].rules,

      'ts/return-await': 2,


It should be noted that the ts plugin appears twice in the configuration. The shared configurations use a longer namespace than the one intended for usage.

Answer №2

I've had success with this solution, but I still feel like the API could use some simplification.

const typescriptPlugin = require("@typescript-eslint/eslint-plugin");
const typescriptParser = require("@typescript-eslint/parser");

const tsOverrideConfig = typescriptPlugin.configs["eslint-recommended"].overrides[0];
const tsRecommemdedConfig = typescriptPlugin.configs.recommended;
const files = ["**/*.ts", "**/*.tsx"];

module.exports = [
  "eslint:recommended",
  {
    files,
    linterOptions: {
      reportUnusedDisableDirectives: true,
    },
    languageOptions: {
      parser: typescriptParser,
    },
    plugins: {
      "@typescript-eslint": typescriptPlugin,
    },
  },
  { files, rules: tsOverrideConfig.rules },
  { files, rules: tsRecommemdedConfig.rules },
];

Answer №3

Here's my custom flat configuration file eslint.config.mjs that includes the following key features:

  • Integration with Typescript parser and plugin
  • Support for Node.js and Mocha environments
  • Utilization of ESM format across projects, including CJS setups
import globals from "globals";
import tsParser from "@typescript-eslint/parser";
import tsPlugin from "@typescript-eslint/eslint-plugin";
import eslintJsPlugin from "@eslint/js";

export default [
  {
    rules: eslintJsPlugin.configs.recommended.rules,
  },
  {
    files: [ "**/*.ts" ],
    languageOptions: {
      parser: tsParser,
      globals: globals.node,
    },
    plugins: {
      "@typescript-eslint": tsPlugin,
    },
    rules: {
      ...tsPlugin.configs.recommended.rules,
      "no-console": "error",
    }
  },
  {
    files: [ "test/**/*.ts" ],
    languageOptions: {
      globals: globals.mocha,
    },
  },
];

To execute eslint using this configuration in a CommonJS project, I rely on the specified command:

ESLINT_USE_FLAT_CONFIG=true npx eslint src test

Answer №4

Take a look at the flatConfig example available in the microsoft/vscode-eslint repository (➜ VSCode ESLint extension).

For instance: eslint.config.js

const globals = require('globals');
const typescriptParser =  require('@typescript-eslint/parser');
const typescriptPlugin = require('@typescript-eslint/eslint-plugin');

module.exports = [
    "eslint:recommended",
    {
        files: ["**/*.js"],
        languageOptions: {
            parserOptions: {
                sourceType: "module"
            },
            globals: {
                ...globals.browser,
                ...globals.node,
                ...globals.es6,
                ...globals.commonjs
            }
        },
    },
    {
        files: ["sub/*.js"],
        rules: {
            "no-undef": "warn",
            "no-console": "warn"
        }
    },
    {
        files: ["*.ts", "**/*.ts"],
        plugins: {
            "@typescript-eslint": typescriptPlugin
        },
        languageOptions: {
            parser: typescriptParser,
            parserOptions: {
                project: "./tsconfig.json",
                sourceType: "module",
                ecmaVersion: 2020
            }
        },
        rules: {
            "semi": "off",
            "@typescript-eslint/semi": "error",
            "no-extra-semi": "warn",
            "curly": "warn",
            "quotes": ["error", "single", { "allowTemplateLiterals": true } ],
            "eqeqeq": "error",
            "indent": "off",
            "@typescript-eslint/indent": ["warn", "tab", { "SwitchCase": 1 } ],
            "@typescript-eslint/no-floating-promises": "error"
        }
    }
]
Discover more about ESLint's new config system with these blog posts (flat config):
  1. ESLint's new config system, Part 1: Background
  2. ESLint's new config system, Part 2: Introduction to flat config (particularly interesting)
  3. ESLint's new config system, Part 3: Developer preview

Answer №5

It is worth noting that typescript-eslint proposes an alternative approach for defining their eslint Flat Config:

For example: eslint.config.js

// @ts-check

import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';

export default tseslint.config(
  eslint.configs.recommended,
  ...tseslint.configs.recommended,
);

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 with Promise.all and forEach within a nested array

When working on a Node app with typescript, I encountered the need to iterate through an array while calling an asynchronous function inside the loop to fetch information about related items for each item in the array. The function is called for each relat ...

How can I pass DOCUMENT in Angular?

In my directive, I use dependency injection to access the DOCUMENT and set up an event listener: constructor(@Inject(DOCUMENT) private document: Document) {} ngOnInit() { this.document.addEventListener('click', this.clicked, true); } @Bound ...

Types with conditions but no common parameter

I am looking to define my props as either type A or B. For instance export default function App() { type Checkbox = { type: "checkbox"; checked: boolean; }; type Dropdown = { type: "dropdown"; options: Array<an ...

Using Angular 4 to transfer data from a dynamic modal to a component

Currently implementing material design, I have set up a dialogService for dynamically loading MdDialog. My goal is to create a search dialog with filters that, upon submission, directs the user to a search-results component route. However, I am struggling ...

Encountering an issue with creating an App Runner on AWS CDK

Attempting to deploy my application using App Runner within AWS via CDK. Utilizing the reference from https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-apprunner.Service.html. Upon deployment, encountering the following error: create_failed: R ...

Why is NestJs having trouble resolving dependencies?

Recently delving into NestJs, I followed the configuration instructions outlined in https://docs.nestjs.com/techniques/database, but I am struggling to identify the issue within my code. Error: Nest cannot resolve dependencies of the AdminRepository ...

Enhancing Readability of Public Static Member Variables in Typescript

In my node application, I am utilizing typescript and winston for logging purposes. One key element of my setup is the "Logger" class which consists of a "logger" member and an "init()" function. By exporting this class, I understand that the "logger" memb ...

Utilize JavaScript libraries in a TypeScript project

Looking to integrate a payment system called iyzico into my project. The iyzico payment library can be found here. However, there are no types available for it. How can I utilize this library in my Node.js TypeScript Express backend project? I attempted t ...

Import statements cannot be used outside of a module when working with a private npm package in cucumber.js

Utilizing cucumberjs to test various components of my project has been successful. However, I encountered an issue in one step where I utilize a zod schema that is defined within a private npm module: // within the private npm package: // constant.js impor ...

Is there a way to customize Material UI theme types and make adjustments to existing types using Typescript?

One way to customize the material ui theme is by extending its type and adding new properties, as shown here: For example, if we want to add an appDrawer property, it can be done like this: declare module '@material-ui/core/styles/createMuiTheme&apos ...

Encountering the "potential null object" TypeScript issue when utilizing template ref data in Vue

Currently, I am trying to make modifications to the CSS rules of an <h1> element with a reference ref="header". However, I have encountered a TypeScript error that is preventing me from doing so. const header = ref<HTMLElement | null> ...

Aggregating and organizing all TypeScript files within the project while preserving the file hierarchy

Looking to utilize a task runner such as Grunt or Gulp to compile TS to JS files in various locations within the project folder. The goal is to ensure that the outputted JS files are placed in the same directory where the project will look for them alongsi ...

Having trouble getting material-ui container to work with custom breakpoints in TypeScript?

Currently, I am exploring material-ui and typescript within my educational project. However, I have encountered a perplexing issue for which I am seeking assistance. In this project, I utilize custom breakpoints in the material-ui theme settings. import { ...

The attribute 'finally' is not found on the data type 'Promise<void>'

I've been attempting to implement the finally method on a promise but continue running into this issue. Property 'finally' does not exist on type 'Promise<void>'. After researching similar problems, I found suggestions to a ...

Utilizing Javascript to load and parse data retrieved from an HTTP request

Within my application, a server with a rest interface is utilized to manage all database entries. Upon user login, the objective is to load and map all user data from database models to usable models. A key distinction between the two is that database mode ...

A guide on converting TypeScript to JavaScript while utilizing top-level await

Exploring the capabilities of top-level await introduced with TypeScript 3.8 in a NodeJS setting. Here's an example of TypeScript code utilizing this feature: import { getDoctorsPage } from "./utils/axios.provider"; const page = await getDo ...

Perform a calculation where two numbers are multiplied together and the result is added to a third number

I'm just getting started with functional programming and I'm attempting to create a function that multiplies two numbers together and then adds the result to a third number using TypeScript with rambda. My goal is to have a function that takes t ...

How can I convert duplicate code into a function in JavaScript?

I have successfully bound values to a view in my code, but I am concerned about the duplicate nested forEach loops that are currently present. I anticipate that Sonarcube will flag this as redundant code. Can anyone advise me on how to refactor this to avo ...

Accelerated repository uses TypeScript to compile a node application with dependencies managed within a shared workspace

Struggling to set up an express api within a pnpm turborepo workspace. The api relies on @my/shared as a dependency, which is a local workspace package. I have been facing challenges in getting the build process right. It seems like I need to build the s ...

What are some ways to specialize a generic class during its creation in TypeScript?

I have a unique class method called continue(). This method takes a callback and returns the same type of value as the given callback. Here's an example: function continue<T>(callback: () => T): T { // ... } Now, I'm creating a clas ...