How to configure ESLint in a Turborepo monorepo to avoid tsconfigRootDir errors

  • I often get tsconfigRootDir errors?
  • Should I have a root level eslint.config.js?
  • Why was extends used here but not in the others?

sw :backhand_index_pointing_right: I’d recommend:

  • Have a root eslint.config.js

  • Set:

parserOptions: {
  project: true,
  tsconfigRootDir: process.cwd(),
}

:backhand_index_pointing_right: And inside each package:

parserOptions: {
  project: "./tsconfig.json",
  tsconfigRootDir: __dirname,
}

That fixes most tsconfigRootDir issues :+1:

Also quick note: if you’re using the new flat config, it doesn’t use extends anymore — that’s why it looks inconsistent. For the tsconfigRootDir issue, do this:

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

export default [
  js.configs.recommended,
  ...tseslint.configs.recommended,

  {
    files: ["**/*.ts", "**/*.tsx"],
    languageOptions: {
      parserOptions: {
        project: true,
        tsconfigRootDir: process.cwd(),
      },
    },
  },
];

:backhand_index_pointing_right: And if you have configs inside each package:

tsconfigRootDir: import.meta.dirname

That’s it — flat config = no extends, and tsconfigRootDir must be explicit :+1: Try this repo to on Github to see more about flat config

Thanks for pointing me in the right direction. I followed your advice and it worked.

I did make some adjustments though.

According to Typed Linting with Project Service | typescript-eslint .

-project: true,
+projectService: true,

But even after that, im getting the following error

Parsing error: /project_path/apps/site/eslint.config.js was not found by the project service. Consider either including it in the tsconfig.json or including it in allowDefaultProject. eslint

So I also added this:

-projectService: true,
+projectService: { allowDefaultProject: ['*.js'] },

originally had allowDefaultProject set to eslint.config.js. Not sure which one makes more sense, thoughts?