From 533d973a7775ff4a04871132a6daaa882959cda4 Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger <53019676+kirkwaiblinger@users.noreply.github.com> Date: Mon, 25 Aug 2025 18:37:26 -0600 Subject: [PATCH 01/13] WIP - deprecate tseslint.config() --- docs/packages/TypeScript_ESLint.mdx | 92 ++++++++++++++++--- .../typescript-eslint/src/config-helper.ts | 3 + 2 files changed, 81 insertions(+), 14 deletions(-) diff --git a/docs/packages/TypeScript_ESLint.mdx b/docs/packages/TypeScript_ESLint.mdx index 9fc886d872bd..17316477253b 100644 --- a/docs/packages/TypeScript_ESLint.mdx +++ b/docs/packages/TypeScript_ESLint.mdx @@ -16,12 +16,12 @@ This package is the main entrypoint that you can use to consume our tooling with This package exports the following: -| Name | Description | -| --------- | -------------------------------------------------------------------------------------- | -| `config` | A utility function for creating type-safe flat configs -- see [`config(...)`](#config) | -| `configs` | [Shared ESLint (flat) configs](../users/Shared_Configurations.mdx) | -| `parser` | A re-export of [`@typescript-eslint/parser`](./Parser.mdx) | -| `plugin` | A re-export of [`@typescript-eslint/eslint-plugin`](./ESLint_Plugin.mdx) | +| Name | Description | +| --------------------- | -------------------------------------------------------------------------------------- | +| `config` (deprecated) | A utility function for creating type-safe flat configs -- see [`config(...)`](#config) | +| `configs` | [Shared ESLint (flat) configs](../users/Shared_Configurations.mdx) | +| `parser` | A re-export of [`@typescript-eslint/parser`](./Parser.mdx) | +| `plugin` | A re-export of [`@typescript-eslint/eslint-plugin`](./ESLint_Plugin.mdx) | ## Installation @@ -37,9 +37,10 @@ We recommend getting started by using the `tseslint.config()` helper function in // @ts-check import eslint from '@eslint/js'; +import { defineConfig } from 'eslint/config'; import tseslint from 'typescript-eslint'; -export default tseslint.config( +export default defineConfig( eslint.configs.recommended, tseslint.configs.recommended, ); @@ -47,16 +48,16 @@ export default tseslint.config( This config file exports a flat config that enables both the [core ESLint recommended config](https://www.npmjs.com/package/@eslint/js) and [our recommended config](../users/Shared_Configurations.mdx#recommended). -:::note -ESLint also provides a `defineConfig()` helper similar to `tseslint.config()`. -However, there is a types incompatibility issue that causes type errors to incorrectly be reported when mixing typescript-eslint's configs and `defineConfig()`. -For now we recommend using `tseslint.config()` for use with typescript-eslint configs. +### `config(...)` (deprecated) -See [typescript-eslint#10899](https://github.com/typescript-eslint/typescript-eslint/issues/10899) for more details. +:::danger -::: +The `config(...)` utility function was **deprecated** in favor of ESLint core's [`defineConfig()`]() in [#10935](https://github.com/typescript-eslint/typescript-eslint/issues/10935). +See [the migration guide below](#migrating-to-defineconfig) for more details. -### `config(...)` +The documentation here is preserved for historical reference and migration purposes. + +::: `tseslint.config(...)` takes in any number of ESLint config objects, each of which may additionally include an `extends` array of configs to extend. `tseslint.config(...)` returns the equivalent ESLint config of applying the rest of the settings for each extension. @@ -168,6 +169,69 @@ export default tseslint.config({ }); ``` +#### Migrating to `defineConfig()` + +The core `defineConfig()` helper is a nearly exact clone of `tseslint.config(...)` that was [first released in ESLint v9.22.0](https://eslint.org/blog/2025/03/eslint-v9.22.0-released/). +See [the ESLint blog post](https://eslint.org/blog/2025/03/flat-config-extends-define-config-global-ignores/#support-for-older-eslint-versions) for info on how to use `defineConfig()` with older versions of ESLint. + +At the time of writing there are a small number of known edge cases in which the two functions have different functionality. + +1. Overriding `files` in `extends`. + When `files` is provided in both a base object and an extension, `tseslint.config(...)` _overrides_ the `files` property in the extension, whereas `defineConfig()` semantically intersects the two provided `files` specifiers. + + ```ts title="eslint.config.mjs" + import tseslint from 'typescript-eslint'; + + export default tseslint.config({ + files: ['a.ts'], + extends: [ + { + files: ['b.ts'], + rules: { + 'some-rule': 'error', + }, + }, + ], + }); + + // equivalent to + + export default { + files: ['a.ts'], + rules: { 'some-rule': 'error' }, + }; + ``` + + ```ts title="eslint.config.mjs" + import { defineConfig } from 'eslint/config'; + + export default defineConfig({ + files: ['a.ts'], + extends: [ + { + files: ['b.ts'], + rules: { + 'some-rule': 'error', + }, + }, + ], + }); + + // equivalent to + + // the base config ensures that 'b.ts' is still included in the lint run, + // but otherwise the config has no effect, due to the intersection of 'a.ts' + // and 'b.ts' being empty + export default { + files: ['a.ts'], + }; + ``` + +2. Type declarations (only applies to users who typecheck their eslint configs). + There are slight differences in the way types are declared between the two functions, which may cause typechecking errors when you switch from `tseslint.config(...)` to `defineConfig()` in some cases. + See [#10899](https://github.com/typescript-eslint/typescript-eslint/issues/10899) for an example. + Type errors such as these do not indicate a runtime problem and can safely be ignored. + ### Manual usage [typescript-eslint's recommended and stylistic configurations](../users/configs) specify typescript-eslint `parser` and `plugin` options for you, so there is no need to manually provide those. diff --git a/packages/typescript-eslint/src/config-helper.ts b/packages/typescript-eslint/src/config-helper.ts index 51456475734f..712651b804db 100644 --- a/packages/typescript-eslint/src/config-helper.ts +++ b/packages/typescript-eslint/src/config-helper.ts @@ -88,6 +88,9 @@ export type ConfigArray = TSESLint.FlatConfig.ConfigArray; * }, * ); * ``` + * + * @deprecated ESLint core now provides this functionality via `defineConfig()`, + * which we now recommend instead. See {@link https://typescript-eslint.io/packages/typescript-eslint/#config}. */ export function config( ...configs: InfiniteDepthConfigWithExtends[] From 2e44d3fb7ebf2d2892b70c289ddd7958a2c050ae Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger <53019676+kirkwaiblinger@users.noreply.github.com> Date: Mon, 25 Aug 2025 18:44:48 -0600 Subject: [PATCH 02/13] yup --- docs/packages/TypeScript_ESLint.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/packages/TypeScript_ESLint.mdx b/docs/packages/TypeScript_ESLint.mdx index 17316477253b..56122b78f367 100644 --- a/docs/packages/TypeScript_ESLint.mdx +++ b/docs/packages/TypeScript_ESLint.mdx @@ -31,7 +31,7 @@ npm i typescript-eslint ## Usage -We recommend getting started by using the `tseslint.config()` helper function in your ESLint config: +We recommend getting started by using the default ESLint setup with our shared configs. ```js title="eslint.config.mjs" // @ts-check @@ -52,7 +52,7 @@ This config file exports a flat config that enables both the [core ESLint recomm :::danger -The `config(...)` utility function was **deprecated** in favor of ESLint core's [`defineConfig()`]() in [#10935](https://github.com/typescript-eslint/typescript-eslint/issues/10935). +The `config(...)` utility function was deprecated in favor of ESLint core's [`defineConfig()`]() in [#10935](https://github.com/typescript-eslint/typescript-eslint/issues/10935). See [the migration guide below](#migrating-to-defineconfig) for more details. The documentation here is preserved for historical reference and migration purposes. From 3fff324b6c53c1cbb4c5e549e58eecf1ca354642 Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger <53019676+kirkwaiblinger@users.noreply.github.com> Date: Mon, 25 Aug 2025 18:59:29 -0600 Subject: [PATCH 03/13] gud --- docs/packages/TypeScript_ESLint.mdx | 123 +++++++++++++++------------- 1 file changed, 68 insertions(+), 55 deletions(-) diff --git a/docs/packages/TypeScript_ESLint.mdx b/docs/packages/TypeScript_ESLint.mdx index 56122b78f367..8e0ab84fc658 100644 --- a/docs/packages/TypeScript_ESLint.mdx +++ b/docs/packages/TypeScript_ESLint.mdx @@ -52,7 +52,7 @@ This config file exports a flat config that enables both the [core ESLint recomm :::danger -The `config(...)` utility function was deprecated in favor of ESLint core's [`defineConfig()`]() in [#10935](https://github.com/typescript-eslint/typescript-eslint/issues/10935). +The `config(...)` utility function was deprecated in favor of ESLint core's [`defineConfig(...)`]() in [#10935](https://github.com/typescript-eslint/typescript-eslint/issues/10935). See [the migration guide below](#migrating-to-defineconfig) for more details. The documentation here is preserved for historical reference and migration purposes. @@ -115,7 +115,7 @@ Otherwise it _will not_ impact your ability to use our tooling. #### Flat config `extends` -The `tseslint.config()` utility function also adds handling for the `extends` property on flat config objects. +The `tseslint.config(...)` utility function also adds handling for the `extends` property on flat config objects. This allows you to more easily extend shared configs for specific file patterns whilst also overriding rules/options provided by those configs: ```js @@ -169,66 +169,79 @@ export default tseslint.config({ }); ``` -#### Migrating to `defineConfig()` +#### Migrating to `defineConfig(...)` -The core `defineConfig()` helper is a nearly exact clone of `tseslint.config(...)` that was [first released in ESLint v9.22.0](https://eslint.org/blog/2025/03/eslint-v9.22.0-released/). -See [the ESLint blog post](https://eslint.org/blog/2025/03/flat-config-extends-define-config-global-ignores/#support-for-older-eslint-versions) for info on how to use `defineConfig()` with older versions of ESLint. +The core `defineConfig(...)` helper is a nearly exact clone of `tseslint.config(...)` that was [first released in ESLint v9.22.0](https://eslint.org/blog/2025/03/eslint-v9.22.0-released/). +See [the ESLint blog post](https://eslint.org/blog/2025/03/flat-config-extends-define-config-global-ignores/#support-for-older-eslint-versions) for info on how to use `defineConfig(...)` with older versions of ESLint. At the time of writing there are a small number of known edge cases in which the two functions have different functionality. +{/* prettier-ignore */} 1. Overriding `files` in `extends`. - When `files` is provided in both a base object and an extension, `tseslint.config(...)` _overrides_ the `files` property in the extension, whereas `defineConfig()` semantically intersects the two provided `files` specifiers. - - ```ts title="eslint.config.mjs" - import tseslint from 'typescript-eslint'; - - export default tseslint.config({ - files: ['a.ts'], - extends: [ - { - files: ['b.ts'], - rules: { - 'some-rule': 'error', - }, - }, - ], - }); - - // equivalent to - - export default { - files: ['a.ts'], - rules: { 'some-rule': 'error' }, - }; - ``` - - ```ts title="eslint.config.mjs" - import { defineConfig } from 'eslint/config'; - - export default defineConfig({ - files: ['a.ts'], - extends: [ - { - files: ['b.ts'], - rules: { - 'some-rule': 'error', - }, - }, - ], - }); - - // equivalent to - - // the base config ensures that 'b.ts' is still included in the lint run, - // but otherwise the config has no effect, due to the intersection of 'a.ts' - // and 'b.ts' being empty - export default { - files: ['a.ts'], - }; - ``` + When `files` is provided in both a base object and an extension, `tseslint.config(...)` _overrides_ the `files` property in the extension, whereas `defineConfig(...)` semantically intersects the two provided `files` specifiers. + + + + ```ts title="eslint.config.mjs" + import tseslint from 'typescript-eslint'; + + export default tseslint.config({ + files: ['a.ts'], + extends: [ + { + files: ['b.ts'], + rules: { + 'some-rule': 'error', + }, + }, + ], + }); + + // equivalent to + + export default { + files: ['a.ts'], + rules: { 'some-rule': 'error' }, + }; + ``` + + + + + ```ts title="eslint.config.mjs" + import { defineConfig } from 'eslint/config'; + + export default defineConfig({ + files: ['a.ts'], + extends: [ + { + files: ['b.ts'], + rules: { + 'some-rule': 'error', + }, + }, + ], + }); + + // equivalent to + + // The base config technically ensures that 'b.ts' is still included in + // the lint run, but otherwise the config has no effect, due to the + // intersection of 'a.ts' and 'b.ts' being empty. + export default { + files: ['a.ts'], + }; + ``` + + + + + + + 2. Type declarations (only applies to users who typecheck their eslint configs). - There are slight differences in the way types are declared between the two functions, which may cause typechecking errors when you switch from `tseslint.config(...)` to `defineConfig()` in some cases. + There are slight differences in the way types are declared between the two functions, which may cause typechecking errors when you switch from `tseslint.config(...)` to `defineConfig(...)` in some cases. See [#10899](https://github.com/typescript-eslint/typescript-eslint/issues/10899) for an example. Type errors such as these do not indicate a runtime problem and can safely be ignored. From 4d73b73c4d55f969ada7404e440471735f66be45 Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger <53019676+kirkwaiblinger@users.noreply.github.com> Date: Mon, 25 Aug 2025 19:11:07 -0600 Subject: [PATCH 04/13] issue --- docs/packages/TypeScript_ESLint.mdx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/packages/TypeScript_ESLint.mdx b/docs/packages/TypeScript_ESLint.mdx index 8e0ab84fc658..a69c47005e4b 100644 --- a/docs/packages/TypeScript_ESLint.mdx +++ b/docs/packages/TypeScript_ESLint.mdx @@ -176,6 +176,8 @@ See [the ESLint blog post](https://eslint.org/blog/2025/03/flat-config-extends-d At the time of writing there are a small number of known edge cases in which the two functions have different functionality. +{/* https://github.com/prettier/prettier/issues/17816 */} + {/* prettier-ignore */} 1. Overriding `files` in `extends`. When `files` is provided in both a base object and an extension, `tseslint.config(...)` _overrides_ the `files` property in the extension, whereas `defineConfig(...)` semantically intersects the two provided `files` specifiers. From e81ad55552ebda8347e92b1678ef171be5179c17 Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger <53019676+kirkwaiblinger@users.noreply.github.com> Date: Tue, 26 Aug 2025 10:13:50 -0600 Subject: [PATCH 05/13] switch docs to use defineConfig --- docs/getting-started/Quickstart.mdx | 19 ++++----------- docs/getting-started/Typed_Linting.mdx | 5 ++-- docs/troubleshooting/faqs/ESLint.mdx | 4 ++-- docs/troubleshooting/faqs/Frameworks.mdx | 5 ++-- docs/troubleshooting/faqs/General.mdx | 5 ++-- .../typed-linting/Monorepos.mdx | 4 ++-- .../typed-linting/Performance.mdx | 2 +- docs/troubleshooting/typed-linting/index.mdx | 7 +++--- docs/users/Shared_Configurations.mdx | 23 ++++++++++--------- docs/users/What_About_Formatting.mdx | 3 ++- eslint.config.mjs | 5 ++-- 11 files changed, 39 insertions(+), 43 deletions(-) diff --git a/docs/getting-started/Quickstart.mdx b/docs/getting-started/Quickstart.mdx index 232fe15966d5..8ab6a7504767 100644 --- a/docs/getting-started/Quickstart.mdx +++ b/docs/getting-started/Quickstart.mdx @@ -35,9 +35,9 @@ Next, create an `eslint.config.mjs` config file in the root of your project, and // @ts-check import eslint from '@eslint/js'; -import tseslint from 'typescript-eslint'; +import { defineConfig } from 'eslint/config'; -export default tseslint.config( +export default defineConfig( eslint.configs.recommended, tseslint.configs.recommended, ); @@ -47,21 +47,10 @@ This code will enable our [recommended configuration](../users/Shared_Configurat #### Details -- `tseslint.config(...)` is an **_optional_** helper function — see [`typescript-eslint`'s `config(...)`](../packages/TypeScript_ESLint.mdx#config). +- `defineConfig(...)` is an optional helper function built in to current versions of eslint. See [the eslint docs](https://eslint.org/docs/latest/use/configure/configuration-files) for more detail. - `'@eslint/js'` / `eslint.configs.recommended` turns on [eslint's recommended config](https://www.npmjs.com/package/@eslint/js). - `tseslint.configs.recommended` turns on [our recommended config](../users/Shared_Configurations.mdx#recommended). -
-Aside on ESLint's `defineConfig()` - -ESLint also provides a `defineConfig()` helper similar to `tseslint.config()`. -However, there is a types incompatibility issue that causes type errors to incorrectly be reported when mixing typescript-eslint's configs and `defineConfig()`. -For now we recommend using `tseslint.config()` for use with typescript-eslint's configs. - -See [typescript-eslint#10899](https://github.com/typescript-eslint/typescript-eslint/issues/10899) for more details. - -
-
Aside on file extensions @@ -111,7 +100,7 @@ We recommend you consider enabling the following two configs: - [`stylistic`](../users/Shared_Configurations.mdx#stylistic): additional rules that enforce consistent styling without significantly catching bugs or changing logic. ```js title="eslint.config.mjs" -export default tseslint.config( +export default defineConfig( eslint.configs.recommended, // Remove this line tseslint.configs.recommended, diff --git a/docs/getting-started/Typed_Linting.mdx b/docs/getting-started/Typed_Linting.mdx index 95f225038dd3..bc36f5589735 100644 --- a/docs/getting-started/Typed_Linting.mdx +++ b/docs/getting-started/Typed_Linting.mdx @@ -20,9 +20,10 @@ To enable typed linting, there are two small changes you need to make to your co ```js title="eslint.config.mjs" import eslint from '@eslint/js'; +import { defineConfig } from 'eslint/config'; import tseslint from 'typescript-eslint'; -export default tseslint.config( +export default defineConfig( eslint.configs.recommended, // Remove this line tseslint.configs.recommended, @@ -99,7 +100,7 @@ If you enabled the [`strict` shared config](../users/Shared_Configurations.mdx#s ```js title="eslint.config.mjs" -export default tseslint.config( +export default defineConfig( eslint.configs.recommended, // Removed lines start tseslint.configs.strict, diff --git a/docs/troubleshooting/faqs/ESLint.mdx b/docs/troubleshooting/faqs/ESLint.mdx index d1a5cdf0d809..a07e16a2f798 100644 --- a/docs/troubleshooting/faqs/ESLint.mdx +++ b/docs/troubleshooting/faqs/ESLint.mdx @@ -49,9 +49,9 @@ Note, that for a mixed project including JavaScript and TypeScript, the `no-unde ```js title="eslint.config.mjs" -import tseslint from 'typescript-eslint'; +import { defineConfig } from 'eslint/config'; -export default tseslint.config( +export default defineConfig( // ... the rest of your config ... { files: ['**/*.{ts,tsx,mts,cts}'], diff --git a/docs/troubleshooting/faqs/Frameworks.mdx b/docs/troubleshooting/faqs/Frameworks.mdx index fc0e559b56fa..f80be6a84296 100644 --- a/docs/troubleshooting/faqs/Frameworks.mdx +++ b/docs/troubleshooting/faqs/Frameworks.mdx @@ -19,7 +19,7 @@ See [Changes to `extraFileExtensions` with `projectService`](../typed-linting/Pe ```js title="eslint.config.mjs" -export default tseslint.config( +export default defineConfig( // ... the rest of your config ... { languageOptions: { @@ -61,10 +61,11 @@ If you are running into issues parsing .vue files, it might be because parsers l ```js title="eslint.config.mjs" import tseslint from 'typescript-eslint'; +import { defineConfig } from 'eslint/config'; // Add this line import vueParser from 'vue-eslint-parser'; -export default tseslint.config( +export default defineConfig( // ... the rest of your config ... { languageOptions: { diff --git a/docs/troubleshooting/faqs/General.mdx b/docs/troubleshooting/faqs/General.mdx index 53b752ab9b80..aa04254f59b9 100644 --- a/docs/troubleshooting/faqs/General.mdx +++ b/docs/troubleshooting/faqs/General.mdx @@ -36,7 +36,7 @@ Some examples ```js title="eslint.config.mjs" -export default tseslint.config( +export default defineConfig( // ... the rest of your config ... { rules: { @@ -242,9 +242,10 @@ For example, the following config enables only the recommended config's type-che {/* prettier-ignore */} ```js title="eslint.config.mjs" import eslint from '@eslint/js'; +import { defineConfig } from 'eslint/config'; import tseslint from 'typescript-eslint'; -export default tseslint.config( +export default defineConfig( tseslint.configs.recommendedTypeCheckedOnly, { languageOptions: { diff --git a/docs/troubleshooting/typed-linting/Monorepos.mdx b/docs/troubleshooting/typed-linting/Monorepos.mdx index 85cc6ef264db..2364b9defe24 100644 --- a/docs/troubleshooting/typed-linting/Monorepos.mdx +++ b/docs/troubleshooting/typed-linting/Monorepos.mdx @@ -56,7 +56,7 @@ For each file being linted, the first matching project path will be used as its ```js title="eslint.config.mjs" -export default tseslint.config( +export default defineConfig( eslint.configs.recommended, tseslint.configs.recommendedTypeChecked, { @@ -108,7 +108,7 @@ Instead of globs that use `**` to recursively check all folders, prefer paths th ```js title="eslint.config.mjs" -export default tseslint.config( +export default defineConfig( eslint.configs.recommended, tseslint.configs.recommendedTypeChecked, { diff --git a/docs/troubleshooting/typed-linting/Performance.mdx b/docs/troubleshooting/typed-linting/Performance.mdx index 29775150a6d6..25fcfd63ef1f 100644 --- a/docs/troubleshooting/typed-linting/Performance.mdx +++ b/docs/troubleshooting/typed-linting/Performance.mdx @@ -180,7 +180,7 @@ Instead of globs that use `**` to recursively check all folders, prefer paths th import eslint from '@eslint/js'; import tseslint from 'typescript-eslint'; -export default tseslint.config( +export default defineConfig( eslint.configs.recommended, tseslint.configs.recommendedRequiringTypeChecking, { diff --git a/docs/troubleshooting/typed-linting/index.mdx b/docs/troubleshooting/typed-linting/index.mdx index 6681b1069b5d..5b76f5c53ad3 100644 --- a/docs/troubleshooting/typed-linting/index.mdx +++ b/docs/troubleshooting/typed-linting/index.mdx @@ -30,9 +30,10 @@ For example, to disable type-checked linting on all `.js` files: ```js title="eslint.config.mjs" +import defineConfig from 'eslint/config'; import tseslint from 'typescript-eslint'; -export default tseslint.config( +export default defineConfig( // ... the rest of your config ... { files: ['**/*.js'], @@ -69,7 +70,7 @@ You can combine ESLint's [overrides](https://eslint.org/docs/latest/use/configur ```js title="eslint.config.mjs" -export default tseslint.config( +export default defineConfig( eslint.configs.recommended, tseslint.configs.recommendedTypeChecked, tseslint.configs.stylisticTypeChecked, @@ -297,7 +298,7 @@ For example, if you use a specific `tsconfig.eslint.json` for linting, you'd spe ```js title="eslint.config.mjs" -export default tseslint.config({ +export default defineConfig({ // ... languageOptions: { parserOptions: { diff --git a/docs/users/Shared_Configurations.mdx b/docs/users/Shared_Configurations.mdx index e77d68bcf6a2..ea4c554e37af 100644 --- a/docs/users/Shared_Configurations.mdx +++ b/docs/users/Shared_Configurations.mdx @@ -21,9 +21,10 @@ See [Getting Started > Quickstart](../getting-started/Quickstart.mdx) first to s // @ts-check import eslint from '@eslint/js'; +import { defineConfig } from 'eslint/config'; import tseslint from 'typescript-eslint'; -export default tseslint.config( +export default defineConfig( eslint.configs.recommended, tseslint.configs.recommended, ); @@ -37,7 +38,7 @@ If your project does not enable [typed linting](../getting-started/Typed_Linting ```js title="eslint.config.mjs" -export default tseslint.config( +export default defineConfig( eslint.configs.recommended, tseslint.configs.recommended, tseslint.configs.stylistic, @@ -70,7 +71,7 @@ If your project enables [typed linting](../getting-started/Typed_Linting.mdx), w ```js title="eslint.config.mjs" -export default tseslint.config( +export default defineConfig( eslint.configs.recommended, tseslint.configs.recommendedTypeChecked, tseslint.configs.stylisticTypeChecked, @@ -127,7 +128,7 @@ These rules are those whose reports are almost always for a bad practice and/or {/* prettier-ignore */} ```js title="eslint.config.mjs" -export default tseslint.config( +export default defineConfig( tseslint.configs.recommended, ); ``` @@ -156,7 +157,7 @@ Rules newly added in this configuration are similarly useful to those in `recomm {/* prettier-ignore */} ```js title="eslint.config.mjs" -export default tseslint.config( +export default defineConfig( tseslint.configs.recommendedTypeChecked, ); ``` @@ -185,7 +186,7 @@ Rules added in `strict` are more opinionated than recommended rules and might no {/* prettier-ignore */} ```js title="eslint.config.mjs" -export default tseslint.config( +export default defineConfig( tseslint.configs.strict, ); ``` @@ -224,7 +225,7 @@ Rules newly added in this configuration are similarly useful (and opinionated) t {/* prettier-ignore */} ```js title="eslint.config.mjs" -export default tseslint.config( +export default defineConfig( tseslint.configs.strictTypeChecked, ); ``` @@ -263,7 +264,7 @@ These rules are generally opinionated about enforcing simpler code patterns. {/* prettier-ignore */} ```js title="eslint.config.mjs" -export default tseslint.config( +export default defineConfig( tseslint.configs.stylistic, ); ``` @@ -295,7 +296,7 @@ Rules newly added in this configuration are similarly opinionated to those in `s {/* prettier-ignore */} ```js title="eslint.config.mjs" -export default tseslint.config( +export default defineConfig( tseslint.configs.stylisticTypeChecked, ); ``` @@ -362,7 +363,7 @@ If you use type-aware rules from other plugins, you will need to manually disabl ```js title="eslint.config.mjs" -export default tseslint.config( +export default defineConfig( eslint.configs.recommended, tseslint.configs.recommendedTypeChecked, { @@ -426,7 +427,7 @@ Additionally, it enables rules that promote using the more modern constructs Typ ```js title="eslint.config.mjs" -export default tseslint.config( +export default defineConfig( eslint.configs.recommended, tseslint.configs.eslintRecommended, ); diff --git a/docs/users/What_About_Formatting.mdx b/docs/users/What_About_Formatting.mdx index a070fdfccfb2..ace2aa4ebd97 100644 --- a/docs/users/What_About_Formatting.mdx +++ b/docs/users/What_About_Formatting.mdx @@ -50,11 +50,12 @@ Using this config by adding it to the end of your `extends`: // @ts-check import eslint from '@eslint/js'; +import { defineConfig } from 'eslint/config'; import someOtherConfig from 'eslint-config-other-configuration-that-enables-formatting-rules'; import prettierConfig from 'eslint-config-prettier'; import tseslint from 'typescript-eslint'; -export default tseslint.config( +export default defineConfig( eslint.configs.recommended, tseslint.configs.recommended, someOtherConfig, diff --git a/eslint.config.mjs b/eslint.config.mjs index b7b469b0dd63..588ead5b8281 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -4,6 +4,7 @@ import eslintCommentsPlugin from '@eslint-community/eslint-plugin-eslint-comment import { fixupConfigRules, fixupPluginRules } from '@eslint/compat'; import { FlatCompat } from '@eslint/eslintrc'; import eslint from '@eslint/js'; +import { defineConfig } from 'eslint/config'; import tseslintInternalPlugin from '@typescript-eslint/eslint-plugin-internal'; import vitestPlugin from '@vitest/eslint-plugin'; import eslintPluginPlugin from 'eslint-plugin-eslint-plugin'; @@ -28,7 +29,7 @@ const restrictNamedDeclarations = { selector: 'ExportNamedDeclaration[declaration=null][source=null]', }; -export default tseslint.config( +export default defineConfig( // register all of the plugins up-front { name: 'register-all-plugins', @@ -43,6 +44,7 @@ export default tseslint.config( // @ts-expect-error -- https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/pull/1038 ['jsx-a11y']: jsxA11yPlugin.flatConfigs.recommended.plugins['jsx-a11y'], ['perfectionist']: perfectionistPlugin, + // @ts-expect-error -- https://github.com/vitest-dev/eslint-plugin-vitest/issues/737 ['vitest']: vitestPlugin, // https://github.com/facebook/react/issues/28313 ['react']: reactPlugin, @@ -363,7 +365,6 @@ export default tseslint.config( // test file specific configuration { extends: [ - // @ts-expect-error -- uses `string` instead of `off` | `readonly` | `writable` for the globals setting. vitestPlugin.configs.env, { rules: { From 7fb7e71ad433563b965ee4de9e3f5f432cfe6e9a Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger <53019676+kirkwaiblinger@users.noreply.github.com> Date: Tue, 26 Aug 2025 10:14:46 -0600 Subject: [PATCH 06/13] add back import --- docs/getting-started/Quickstart.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/getting-started/Quickstart.mdx b/docs/getting-started/Quickstart.mdx index 8ab6a7504767..0db759fdd584 100644 --- a/docs/getting-started/Quickstart.mdx +++ b/docs/getting-started/Quickstart.mdx @@ -36,6 +36,7 @@ Next, create an `eslint.config.mjs` config file in the root of your project, and import eslint from '@eslint/js'; import { defineConfig } from 'eslint/config'; +import tseslint from 'typescript-eslint'; export default defineConfig( eslint.configs.recommended, From 395c24ba8a37a7fe1baa3b608a92ec8aa74a50e4 Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger <53019676+kirkwaiblinger@users.noreply.github.com> Date: Tue, 26 Aug 2025 23:39:29 -0700 Subject: [PATCH 07/13] lint --- eslint.config.mjs | 2 +- packages/typescript-eslint/tests/config-helper.test.ts | 2 ++ packages/typescript-eslint/tests/type-compatibility.test-d.ts | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index 588ead5b8281..9241cbee26a5 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -4,7 +4,6 @@ import eslintCommentsPlugin from '@eslint-community/eslint-plugin-eslint-comment import { fixupConfigRules, fixupPluginRules } from '@eslint/compat'; import { FlatCompat } from '@eslint/eslintrc'; import eslint from '@eslint/js'; -import { defineConfig } from 'eslint/config'; import tseslintInternalPlugin from '@typescript-eslint/eslint-plugin-internal'; import vitestPlugin from '@vitest/eslint-plugin'; import eslintPluginPlugin from 'eslint-plugin-eslint-plugin'; @@ -16,6 +15,7 @@ import reactPlugin from 'eslint-plugin-react'; import reactHooksPlugin from 'eslint-plugin-react-hooks'; import regexpPlugin from 'eslint-plugin-regexp'; import unicornPlugin from 'eslint-plugin-unicorn'; +import { defineConfig } from 'eslint/config'; import globals from 'globals'; import url from 'node:url'; import tseslint from 'typescript-eslint'; diff --git a/packages/typescript-eslint/tests/config-helper.test.ts b/packages/typescript-eslint/tests/config-helper.test.ts index 8b4a151a32cf..7b3288df295f 100644 --- a/packages/typescript-eslint/tests/config-helper.test.ts +++ b/packages/typescript-eslint/tests/config-helper.test.ts @@ -2,6 +2,8 @@ import type { TSESLint } from '@typescript-eslint/utils'; import tseslint from '../src/index.js'; +/* eslint @typescript-eslint/no-deprecated: ["error", { "allow": [{ "from": "file", "name": "config", "path": "packages/typescript-eslint/src/config-helper.ts" }] }] */ + describe('config helper', () => { it('works without extends', () => { expect( diff --git a/packages/typescript-eslint/tests/type-compatibility.test-d.ts b/packages/typescript-eslint/tests/type-compatibility.test-d.ts index b0e2f71b81d2..dfcf11cbd2f3 100644 --- a/packages/typescript-eslint/tests/type-compatibility.test-d.ts +++ b/packages/typescript-eslint/tests/type-compatibility.test-d.ts @@ -2,6 +2,8 @@ import { defineConfig } from 'eslint/config'; import tseslint from '../src/index'; +/* eslint @typescript-eslint/no-deprecated: ["error", { "allow": [{ "from": "file", "name": "config", "path": "packages/typescript-eslint/src/config-helper.ts" }] }] */ + describe('test for compatibility with config helpers', () => { test('exported plugin is compatible with tseslint.config()', () => { tseslint.config({ From 4bad07b673875c19c2b2738bff5d3f4f55476151 Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger <53019676+kirkwaiblinger@users.noreply.github.com> Date: Wed, 27 Aug 2025 10:08:44 -0700 Subject: [PATCH 08/13] more spots --- docs/packages/TypeScript_ESLint.mdx | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/packages/TypeScript_ESLint.mdx b/docs/packages/TypeScript_ESLint.mdx index a69c47005e4b..734d8fa71f0c 100644 --- a/docs/packages/TypeScript_ESLint.mdx +++ b/docs/packages/TypeScript_ESLint.mdx @@ -174,7 +174,7 @@ export default tseslint.config({ The core `defineConfig(...)` helper is a nearly exact clone of `tseslint.config(...)` that was [first released in ESLint v9.22.0](https://eslint.org/blog/2025/03/eslint-v9.22.0-released/). See [the ESLint blog post](https://eslint.org/blog/2025/03/flat-config-extends-define-config-global-ignores/#support-for-older-eslint-versions) for info on how to use `defineConfig(...)` with older versions of ESLint. -At the time of writing there are a small number of known edge cases in which the two functions have different functionality. +At the time of writing there are a small number of known edge cases in which the two have different functionality. {/* https://github.com/prettier/prettier/issues/17816 */} @@ -199,7 +199,7 @@ At the time of writing there are a small number of known edge cases in which the ], }); - // equivalent to + // is equivalent to export default { files: ['a.ts'], @@ -225,7 +225,7 @@ At the time of writing there are a small number of known edge cases in which the ], }); - // equivalent to + // is equivalent to // The base config technically ensures that 'b.ts' is still included in // the lint run, but otherwise the config has no effect, due to the @@ -260,10 +260,11 @@ You can declare our plugin and parser in your config via this package, for examp // @ts-check import eslint from '@eslint/js'; +import { defineConfig } from 'eslint/config'; import jestPlugin from 'eslint-plugin-jest'; import tseslint from 'typescript-eslint'; -export default tseslint.config({ +export default defineConfig({ plugins: { // highlight-next-line '@typescript-eslint': tseslint.plugin, @@ -305,10 +306,11 @@ This config: // @ts-check import eslint from '@eslint/js'; +import { defineConfig } from 'eslint/config'; import jestPlugin from 'eslint-plugin-jest'; import tseslint from 'typescript-eslint'; -export default tseslint.config( +export default defineConfig( { // config with just ignores is the replacement for `.eslintignore` ignores: ['**/build/**', '**/dist/**', 'src/some/file/to/ignore.ts'], From 50dd8ba959ba4c31b66865eb08a8c4082d8e1441 Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger <53019676+kirkwaiblinger@users.noreply.github.com> Date: Wed, 27 Aug 2025 10:10:09 -0700 Subject: [PATCH 09/13] typo --- docs/packages/TypeScript_ESLint.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/packages/TypeScript_ESLint.mdx b/docs/packages/TypeScript_ESLint.mdx index 734d8fa71f0c..220384b52504 100644 --- a/docs/packages/TypeScript_ESLint.mdx +++ b/docs/packages/TypeScript_ESLint.mdx @@ -227,7 +227,7 @@ At the time of writing there are a small number of known edge cases in which the // is equivalent to - // The base config technically ensures that 'b.ts' is still included in + // The base config technically ensures that 'a.ts' is still included in // the lint run, but otherwise the config has no effect, due to the // intersection of 'a.ts' and 'b.ts' being empty. export default { From b0de934ef2ab1f13c363b449aa9965a9dc683a18 Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger <53019676+kirkwaiblinger@users.noreply.github.com> Date: Wed, 27 Aug 2025 10:15:18 -0700 Subject: [PATCH 10/13] #config-deprecated --- docs/packages/TypeScript_ESLint.mdx | 12 ++++++------ packages/typescript-eslint/src/config-helper.ts | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/packages/TypeScript_ESLint.mdx b/docs/packages/TypeScript_ESLint.mdx index 220384b52504..2982ed1fe952 100644 --- a/docs/packages/TypeScript_ESLint.mdx +++ b/docs/packages/TypeScript_ESLint.mdx @@ -16,12 +16,12 @@ This package is the main entrypoint that you can use to consume our tooling with This package exports the following: -| Name | Description | -| --------------------- | -------------------------------------------------------------------------------------- | -| `config` (deprecated) | A utility function for creating type-safe flat configs -- see [`config(...)`](#config) | -| `configs` | [Shared ESLint (flat) configs](../users/Shared_Configurations.mdx) | -| `parser` | A re-export of [`@typescript-eslint/parser`](./Parser.mdx) | -| `plugin` | A re-export of [`@typescript-eslint/eslint-plugin`](./ESLint_Plugin.mdx) | +| Name | Description | +| --------------------- | ------------------------------------------------------------------------------------------------- | +| `config` (deprecated) | A utility function for creating type-safe flat configs -- see [`config(...)`](#config-deprecated) | +| `configs` | [Shared ESLint (flat) configs](../users/Shared_Configurations.mdx) | +| `parser` | A re-export of [`@typescript-eslint/parser`](./Parser.mdx) | +| `plugin` | A re-export of [`@typescript-eslint/eslint-plugin`](./ESLint_Plugin.mdx) | ## Installation diff --git a/packages/typescript-eslint/src/config-helper.ts b/packages/typescript-eslint/src/config-helper.ts index 712651b804db..758052c62f56 100644 --- a/packages/typescript-eslint/src/config-helper.ts +++ b/packages/typescript-eslint/src/config-helper.ts @@ -90,7 +90,7 @@ export type ConfigArray = TSESLint.FlatConfig.ConfigArray; * ``` * * @deprecated ESLint core now provides this functionality via `defineConfig()`, - * which we now recommend instead. See {@link https://typescript-eslint.io/packages/typescript-eslint/#config}. + * which we now recommend instead. See {@link https://typescript-eslint.io/packages/typescript-eslint/#config-deprecated}. */ export function config( ...configs: InfiniteDepthConfigWithExtends[] From 240396277d856260f0dea9475d42310222d79c40 Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger <53019676+kirkwaiblinger@users.noreply.github.com> Date: Wed, 27 Aug 2025 10:24:05 -0700 Subject: [PATCH 11/13] touchup --- docs/packages/TypeScript_ESLint.mdx | 51 +++++++++++++---------------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/docs/packages/TypeScript_ESLint.mdx b/docs/packages/TypeScript_ESLint.mdx index 2982ed1fe952..3507963b7324 100644 --- a/docs/packages/TypeScript_ESLint.mdx +++ b/docs/packages/TypeScript_ESLint.mdx @@ -176,7 +176,7 @@ See [the ESLint blog post](https://eslint.org/blog/2025/03/flat-config-extends-d At the time of writing there are a small number of known edge cases in which the two have different functionality. -{/* https://github.com/prettier/prettier/issues/17816 */} +{/* https://github.com/prettier/prettier/issues/17816 -- prettier has trouble with the code fences in the custom elements */} {/* prettier-ignore */} 1. Overriding `files` in `extends`. @@ -210,41 +210,36 @@ At the time of writing there are a small number of known edge cases in which the - ```ts title="eslint.config.mjs" - import { defineConfig } from 'eslint/config'; - - export default defineConfig({ - files: ['a.ts'], - extends: [ - { - files: ['b.ts'], - rules: { - 'some-rule': 'error', - }, + ```ts title="eslint.config.mjs" + import { defineConfig } from 'eslint/config'; + + export default defineConfig({ + files: ['a.ts'], + extends: [ + { + files: ['b.ts'], + rules: { + 'some-rule': 'error', }, - ], - }); + }, + ], + }); - // is equivalent to + // is equivalent to - // The base config technically ensures that 'a.ts' is still included in - // the lint run, but otherwise the config has no effect, due to the - // intersection of 'a.ts' and 'b.ts' being empty. - export default { - files: ['a.ts'], - }; - ``` + // The base config technically ensures that 'a.ts' is still included in + // the lint run, but otherwise the config has no effect, due to the + // intersection of 'a.ts' and 'b.ts' being empty. + export default { + files: ['a.ts'], + }; + ``` - - - - 2. Type declarations (only applies to users who typecheck their eslint configs). - There are slight differences in the way types are declared between the two functions, which may cause typechecking errors when you switch from `tseslint.config(...)` to `defineConfig(...)` in some cases. - See [#10899](https://github.com/typescript-eslint/typescript-eslint/issues/10899) for an example. + There are slight differences in the way types are declared between the two functions, which may cause typechecking errors when you switch from `tseslint.config(...)` to `defineConfig(...)` in some cases (see [#10899](https://github.com/typescript-eslint/typescript-eslint/issues/10899) for an example that used to impact typescript-eslint's own configs). Type errors such as these do not indicate a runtime problem and can safely be ignored. ### Manual usage From ce6cda623d1274252723c64d566b5da5aca2f4eb Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger <53019676+kirkwaiblinger@users.noreply.github.com> Date: Wed, 27 Aug 2025 13:37:31 -0700 Subject: [PATCH 12/13] Update docs/getting-started/Quickstart.mdx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Josh Goldberg ✨ --- docs/getting-started/Quickstart.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/getting-started/Quickstart.mdx b/docs/getting-started/Quickstart.mdx index 0db759fdd584..c362a5978ffd 100644 --- a/docs/getting-started/Quickstart.mdx +++ b/docs/getting-started/Quickstart.mdx @@ -48,7 +48,7 @@ This code will enable our [recommended configuration](../users/Shared_Configurat #### Details -- `defineConfig(...)` is an optional helper function built in to current versions of eslint. See [the eslint docs](https://eslint.org/docs/latest/use/configure/configuration-files) for more detail. +- `defineConfig(...)` is an optional helper function built in to current versions of ESLint. See [the ESLint configuration docs](https://eslint.org/docs/latest/use/configure/configuration-files) for more detail. - `'@eslint/js'` / `eslint.configs.recommended` turns on [eslint's recommended config](https://www.npmjs.com/package/@eslint/js). - `tseslint.configs.recommended` turns on [our recommended config](../users/Shared_Configurations.mdx#recommended). From 18a76fc28fc6818c28e957cde8aeb062795dd845 Mon Sep 17 00:00:00 2001 From: Kirk Waiblinger <53019676+kirkwaiblinger@users.noreply.github.com> Date: Wed, 27 Aug 2025 13:37:51 -0700 Subject: [PATCH 13/13] Update docs/packages/TypeScript_ESLint.mdx MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Josh Goldberg ✨ --- docs/packages/TypeScript_ESLint.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/packages/TypeScript_ESLint.mdx b/docs/packages/TypeScript_ESLint.mdx index 3507963b7324..e2c283adf146 100644 --- a/docs/packages/TypeScript_ESLint.mdx +++ b/docs/packages/TypeScript_ESLint.mdx @@ -53,7 +53,7 @@ This config file exports a flat config that enables both the [core ESLint recomm :::danger The `config(...)` utility function was deprecated in favor of ESLint core's [`defineConfig(...)`]() in [#10935](https://github.com/typescript-eslint/typescript-eslint/issues/10935). -See [the migration guide below](#migrating-to-defineconfig) for more details. +See [the `defineConfig` migration guide later](#migrating-to-defineconfig) for more details. The documentation here is preserved for historical reference and migration purposes.