Does anyone have a great eslint+typescript Nuxt 3 setup?

I've been trying to set up eslint and typescript for my Nuxt 3 projects for a while now and not getting this right. There is so much conflicting information online. Does anyone have a great working example where eslint is able to lint with typescript (in js/ts/vue)? For posterity, here is my setup... In my latest attempt I've installed @eslint/js, @nuxt/eslint, @typescript-eslint/parser, eslint, eslint-config-flat-ignore, and typescript. My tsconfig.json is standard:
{
// https://nuxt.com/docs/guide/concepts/typescript
"extends": "./.nuxt/tsconfig.json"
}
{
// https://nuxt.com/docs/guide/concepts/typescript
"extends": "./.nuxt/tsconfig.json"
}
My eslint.config.js looks like this:
import globals from "globals";
import js from "@eslint/js";
import gitignore from "eslint-config-flat-gitignore";
import withNuxt from "./.nuxt/eslint.config.mjs";

export default withNuxt(
gitignore(),
{ files: ["**/*.{js,ts,vue}"] },
{ languageOptions: { globals: globals.browser } },
js.configs.recommended,
{
files: ["**/*.{js,ts,vue}"],
rules: {
// removed for brevity
},
},
{
ignores: ["public/"],
},
);
import globals from "globals";
import js from "@eslint/js";
import gitignore from "eslint-config-flat-gitignore";
import withNuxt from "./.nuxt/eslint.config.mjs";

export default withNuxt(
gitignore(),
{ files: ["**/*.{js,ts,vue}"] },
{ languageOptions: { globals: globals.browser } },
js.configs.recommended,
{
files: ["**/*.{js,ts,vue}"],
rules: {
// removed for brevity
},
},
{
ignores: ["public/"],
},
);
In my nuxt.config.ts I have added @nuxt/eslint to modules. Typescript works just fine in VScode but none of the rules are applied when linting. If I try to add e.g. @typescript-eslint/esplint-plugin to my eslint config, I get a not super helpful complaint: "A config object is using the "extends" key, which is not supported in flat config system." -- Any help appreciated, either links to working eslint+typescript Nuxt3 repos, or specific pointers on what might be going wrong. Thanks!
6 Replies
kapa.ai
kapa.ai4d ago
Hi @Rudo Kemper. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Based on the knowledge sources provided, I can offer some guidance on setting up ESLint with TypeScript for Nuxt 3 projects. The recommended approach has evolved, and there's now a more straightforward way to set this up. For Nuxt 3 projects, the recommended approach is to use the @nuxt/eslint module, which provides an all-in-one ESLint integration. This module generates a project-aware ESLint flat config and is designed to work with the new ESLint flat config format, which is the default since ESLint v9. Here's how you can set it up: 1. Install the required packages:
npm install -D @nuxt/eslint eslint typescript
npm install -D @nuxt/eslint eslint typescript
2. Add the module to your nuxt.config.ts:
export default defineNuxtConfig({
modules: [
'@nuxt/eslint'
],
eslint: {
// options here
}
})
export default defineNuxtConfig({
modules: [
'@nuxt/eslint'
],
eslint: {
// options here
}
})
3. Create an eslint.config.mjs file in your project root with the following content:
import withNuxt from './.nuxt/eslint.config.mjs'

export default withNuxt(
// Your custom flat configs can go here
)
import withNuxt from './.nuxt/eslint.config.mjs'

export default withNuxt(
// Your custom flat configs can go here
)
This setup should automatically handle TypeScript and Vue files without needing to explicitly configure them. The @nuxt/eslint module will generate a project-aware ESLint configuration, including support for TypeScript and Vue files. It's designed to work out of the box with minimal configuration. If you need to customize the configuration further, you can do so in the eslint.config.mjs file. The withNuxt() function returns a chainable FlatConfigComposer instance, allowing you to easily manipulate the ESLint flat config. For example, to override some rules:
import withNuxt from './.nuxt/eslint.config.mjs'

export default withNuxt()
.override('nuxt/typescript', {
rules: {
// Your custom rules here
}
})
import withNuxt from './.nuxt/eslint.config.mjs'

export default withNuxt()
.override('nuxt/typescript', {
rules: {
// Your custom rules here
}
})
This approach should resolve the issues you've been facing with conflicting information and the "extends" key error you mentioned. For more detailed information and advanced configuration options, you can refer to the following resources: - ESLint Module documentation - Nuxt Code Style documentation These sources provide up-to-date information on ESLint integration with Nuxt 3 and TypeScript. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai4d ago
<@910153886306820117> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
m-shum
m-shum4d ago
Seconded. I'm trying to get this working and so far it's been a mess. I'm using the official nuxt eslint package with TS support but the syntax highlighting is all over the place if you leave semicolons disabled. @Rudo Kemper You might have better luck than me with just using the official nuxt module. I gave up on doing all that by hand a long time ago.
Rudo Kemper
Rudo KemperOP4d ago
@m-shum maybe I'm dense and overlooking something obvious, but did you need to do anything in eslint.config.js or elsewhere to enable TS support using @nuxt/eslint? I see in the eslint config checker that typescript rules are being applied, but no warnings/errors output when I run eslint . (I have typescript and vue-tsc installed...)
Omnislash
Omnislash4d ago
I forgot why, but I wanted high control and the stylistic options weren't working how I was expecting it. Did it that way, and works great now : https://ptb.discord.com/channels/473401852243869706/1293909163587534930/1313413917158015036
m-shum
m-shum4d ago
I think out of the box all I needed was to add typescript as a devDependency (as per the docs) – eslint handled the rest for me. I did have to make sure I disabled my Prettier extension and had to fiddle with the default formatter. I don't use vue-tsc (I don't think?). The TS linting definitely works, though you may run into weird formatting behavior that isn't highlighted – for example, if you declare an object type, you have to put a line break between it and anything beneath it, or it could mess up the syntax highlighting of your chosen theme. At least that's what I found.

Did you find this page helpful?