eslint-config-typed 3.0.0 β†’ 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +291 -131
  2. package/dist/configs/plugins.d.mts +1 -1
  3. package/dist/configs/plugins.d.mts.map +1 -1
  4. package/dist/configs/plugins.mjs +3 -2
  5. package/dist/configs/plugins.mjs.map +1 -1
  6. package/dist/configs/typescript-without-rules.mjs +4 -4
  7. package/dist/configs/typescript-without-rules.mjs.map +1 -1
  8. package/dist/configs/typescript.mjs +8 -8
  9. package/dist/configs/typescript.mjs.map +1 -1
  10. package/dist/plugins/total-functions/rules/common.d.mts +2 -1
  11. package/dist/plugins/total-functions/rules/common.d.mts.map +1 -1
  12. package/dist/plugins/total-functions/rules/fp-ts.d.mts +2 -1
  13. package/dist/plugins/total-functions/rules/fp-ts.d.mts.map +1 -1
  14. package/dist/plugins/total-functions/rules/unsafe-assignment-rule.d.mts +2 -1
  15. package/dist/plugins/total-functions/rules/unsafe-assignment-rule.d.mts.map +1 -1
  16. package/dist/rules/eslint-import-rules.d.mts +50 -47
  17. package/dist/rules/eslint-import-rules.d.mts.map +1 -1
  18. package/dist/rules/eslint-import-rules.mjs +55 -54
  19. package/dist/rules/eslint-import-rules.mjs.map +1 -1
  20. package/dist/rules/eslint-react-coding-style-rules.d.mts +1 -1
  21. package/dist/rules/eslint-react-coding-style-rules.d.mts.map +1 -1
  22. package/dist/rules/eslint-react-coding-style-rules.mjs +2 -1
  23. package/dist/rules/eslint-react-coding-style-rules.mjs.map +1 -1
  24. package/dist/rules/typescript-eslint-rules.mjs +1 -1
  25. package/dist/types/flat-config.d.mts.map +1 -1
  26. package/dist/types/rules/eslint-import-rules.d.mts +295 -336
  27. package/dist/types/rules/eslint-import-rules.d.mts.map +1 -1
  28. package/package.json +3 -2
  29. package/src/configs/plugins.mts +5 -3
  30. package/src/configs/typescript-without-rules.mts +4 -4
  31. package/src/configs/typescript.mts +8 -8
  32. package/src/plugins/total-functions/rules/common.mts +1 -1
  33. package/src/plugins/total-functions/rules/fp-ts.mts +1 -1
  34. package/src/plugins/total-functions/rules/no-enums.mts +1 -1
  35. package/src/plugins/total-functions/rules/unsafe-assignment-rule.mts +1 -1
  36. package/src/rules/eslint-import-rules.mts +58 -55
  37. package/src/rules/eslint-react-coding-style-rules.mts +3 -1
  38. package/src/rules/typescript-eslint-rules.mts +1 -1
  39. package/src/types/flat-config.mts +0 -1
  40. package/src/types/rules/eslint-import-rules.mts +305 -362
package/README.md CHANGED
@@ -36,7 +36,7 @@ A comprehensive ESLint configuration package with strongly-typed rule definition
36
36
  - [Rule Types](#rule-types)
37
37
  - [Customization](#customization)
38
38
  - [Override Specific Rules](#override-specific-rules)
39
- - [Use Type-Safe Rule Options](#use-type-safe-rule-options)
39
+ - [Use RulesOptions Types](#use-rulesoptions-types)
40
40
  - [Target Specific Files](#target-specific-files)
41
41
  - [Troubleshooting](#troubleshooting)
42
42
  - [Common Issues](#common-issues)
@@ -49,7 +49,7 @@ A comprehensive ESLint configuration package with strongly-typed rule definition
49
49
 
50
50
  ## Features
51
51
 
52
- - 🎯 **Type-Safe Configuration**: Fully typed ESLint rules and configurations for better IDE support
52
+ - 🎯 **Type-Safe Configuration**: Fully typed ESLint rules **and options** and configurations for better IDE support
53
53
  - πŸ“¦ **Pre-configured Setups**: Ready-to-use configurations for TypeScript, React, Preact, and popular testing frameworks
54
54
  - πŸ“ **Comprehensive Type Definitions**: Complete TypeScript types for all ESLint rules and options
55
55
  - πŸ”„ **ESLint Flat Config Support**: Built for the modern ESLint flat configuration system
@@ -75,15 +75,17 @@ All required ESLint plugins and dependencies are automatically installed.
75
75
 
76
76
  ## Quick Start
77
77
 
78
- Create an `eslint.config.js` file in your project root:
78
+ Create an `eslint.config.js` or `eslint.config.ts` file in your project root:
79
79
 
80
- ```js
80
+ ```tsx
81
81
  import {
82
82
  defineConfig,
83
+ defineKnownRules,
83
84
  eslintConfigForTypeScript,
84
85
  eslintConfigForVitest,
85
- defineKnownRules,
86
+ withDefaultOption,
86
87
  } from 'eslint-config-typed';
88
+
87
89
  // import * as path from 'node:path';
88
90
  // import * as url from 'node:url';
89
91
 
@@ -110,17 +112,15 @@ export default defineConfig([
110
112
  // You can override per-rule settings if necessary.
111
113
  {
112
114
  rules: defineKnownRules({
113
- '@typescript-eslint/no-explicit-any': 'warn',
115
+ '@typescript-eslint/no-explicit-any': withDefaultOption('warn'),
114
116
  '@typescript-eslint/prefer-readonly-parameter-types': 'off',
115
- 'react-hooks/exhaustive-deps': 'warn',
117
+ 'react-hooks/exhaustive-deps': withDefaultOption('warn'),
116
118
  'functional/no-let': [
117
119
  'error',
118
120
  {
119
121
  allowInForLoopInit: true,
120
122
  allowInFunctions: false,
121
- ignoreIdentifierPattern: ignorePattern.filter(
122
- (p) => p !== '^draft',
123
- ),
123
+ ignoreIdentifierPattern: ['^mut_', '^_mut_', '^#mut_'],
124
124
  },
125
125
  ],
126
126
  }),
@@ -151,14 +151,20 @@ npm run lint:fix
151
151
 
152
152
  `defineConfig` wraps your flat configuration array so JavaScript config files get full IntelliSense without relying on JSDoc casts. It keeps literal types intact while returning the config unchanged at runtime.
153
153
 
154
- ```js
155
- import { defineConfig, eslintConfigForTypeScript } from 'eslint-config-typed';
154
+ ```tsx
155
+ import {
156
+ defineConfig,
157
+ defineKnownRules,
158
+ eslintConfigForTypeScript,
159
+ } from 'eslint-config-typed';
160
+
161
+ const thisDir = import.meta.dirname;
156
162
 
157
163
  export default defineConfig([
158
164
  ...eslintConfigForTypeScript({
159
- tsconfigRootDir: import.meta.dirname,
165
+ tsconfigRootDir: thisDir,
160
166
  tsconfigFileName: './tsconfig.json',
161
- packageDirs: [import.meta.dirname],
167
+ packageDirs: [thisDir],
162
168
  }),
163
169
  {
164
170
  rules: defineKnownRules({
@@ -170,93 +176,195 @@ export default defineConfig([
170
176
 
171
177
  This is equivalent to:
172
178
 
173
- ```js
174
- import { eslintConfigForTypeScript } from 'eslint-config-typed';
179
+ ```tsx
180
+ import {
181
+ defineKnownRules,
182
+ eslintConfigForTypeScript,
183
+ type FlatConfig,
184
+ } from 'eslint-config-typed';
185
+
186
+ const thisDir = import.meta.dirname;
175
187
 
176
- /** @type {import('@typescript-eslint/utils/ts-eslint').FlatConfig[]} */
177
188
  export default [
178
189
  ...eslintConfigForTypeScript({
179
- tsconfigRootDir: import.meta.dirname,
190
+ tsconfigRootDir: thisDir,
180
191
  tsconfigFileName: './tsconfig.json',
181
- packageDirs: [import.meta.dirname],
192
+ packageDirs: [thisDir],
182
193
  }),
183
194
  {
184
195
  rules: defineKnownRules({
185
196
  // ...
186
197
  }),
187
198
  },
188
- ];
199
+ ] satisfies readonly FlatConfig[];
189
200
  ```
190
201
 
191
202
  ### defineKnownRules utility
192
203
 
193
- `defineKnownRules` is a helper designed for the `rules` field in ESLint flat configs. It keeps the returned object untouched while giving you type-safe rule names and option inference in editors. When you wrap your overrides with this function you can rely on:
204
+ `defineKnownRules` is a helper designed for the `rules` field in ESLint flat configs. It keeps the returned object untouched while giving you **type-safe rule names and option inference** in editors (like biome.json). When you wrap your overrides with this function you can rely on:
194
205
 
195
206
  - autocomplete and early feedback for rule identifiers, eliminating typo-prone string literals;
196
207
  - strongly typed options for every plugin rule that ships with `eslint-config-typed`, so you can discover valid properties without leaving your editor;
197
208
  - a zero-cost runtime helperβ€”because the object is returned as-is, it blends seamlessly into any flat config block.
198
209
 
210
+ ```tsx
211
+ import {
212
+ defineKnownRules,
213
+ eslintConfigForTypeScript,
214
+ type FlatConfig,
215
+ } from 'eslint-config-typed';
216
+
217
+ const thisDir = import.meta.dirname;
218
+
219
+ export default [
220
+ ...eslintConfigForTypeScript({
221
+ tsconfigRootDir: thisDir,
222
+ tsconfigFileName: './tsconfig.json',
223
+ packageDirs: [thisDir],
224
+ }),
225
+ {
226
+ rules: defineKnownRules({
227
+ // @ts-expect-error typo of rule name
228
+ 'no-restricted-globalsSSSS': 'error',
229
+ // ~~~~~~~~~~~~~~~~~~~~~~~
230
+ }),
231
+ },
232
+ {
233
+ rules: defineKnownRules({
234
+ 'no-unsafe-optional-chaining': [
235
+ 'error',
236
+ // @ts-expect-error typo of an option key
237
+ { disallowArithmeticOperatorsSSSSS: true },
238
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
239
+ ],
240
+ }),
241
+ },
242
+ ] satisfies FlatConfig[];
243
+ ```
244
+
199
245
  ### withDefaultOption utility
200
246
 
201
247
  `withDefaultOption` is a companion helper that highlights rules which ship with option objects. It maps the familiar severity strings to the numeric values ESLint expects: `withDefaultOption('error')` returns `2`, and `withDefaultOption('warn')` returns `1`. Within `defineKnownRules`, rules that provide options require one of these helpers when you want to keep the defaults and only adjust severity. This convention visually distinguishes rules that contain options, reminding users that a rule has configurable options.
202
248
 
203
249
  `defineKnownRules` also reserves `0` for deprecated rules. The resulting severity matrix looks like this:
204
250
 
205
- | Rule type | Allowed severity values in `defineKnownRules` |
206
- | :------------------- | :------------------------------------------------------------- |
207
- | Deprecated rule | `0` |
208
- | Rule without options | `"off"`, `"warn"`, `"error"` |
209
- | Rule with options | `"off"`, `1`, `2`, `["warn", <option>]`, `["error", <option>]` |
251
+ | Rule type | Allowed severity values in `defineKnownRules` |
252
+ | :------------------- | :-------------------------------------------- | ------ | -------- | ------- | ------------------- |
253
+ | Deprecated rule | `0` |
254
+ | Rule without options | `"off" | "warn" | "error"` |
255
+ | Rule with options | `"off" | 1 | 2 | ["warn" | "error", <option>]` |
256
+
257
+ ```tsx
258
+ import {
259
+ defineKnownRules,
260
+ eslintConfigForTypeScript,
261
+ withDefaultOption,
262
+ type FlatConfig,
263
+ } from 'eslint-config-typed';
264
+
265
+ const thisDir = import.meta.dirname;
266
+
267
+ export default [
268
+ ...eslintConfigForTypeScript({
269
+ tsconfigRootDir: thisDir,
270
+ tsconfigFileName: './tsconfig.json',
271
+ packageDirs: [thisDir],
272
+ }),
273
+ {
274
+ rules: defineKnownRules({
275
+ // @ts-expect-error Simply passing the string "error" to a rule with options is not allowed
276
+ 'no-restricted-globals': 'error',
277
+ // ~~~~~~~~~~~~~~~~~~~~
278
+ // ^ Type Error! (Because "no-restricted-globals" has options)
279
+ // NOTE: In addition, some rules, such as "no-restricted-syntax" "and no-restricted-globals", have no effect unless you set the option.
280
+
281
+ // OK
282
+ 'object-shorthand': withDefaultOption('error'),
283
+
284
+ // OK (options are set explicitly)
285
+ 'no-unsafe-optional-chaining': [
286
+ 'error',
287
+ { disallowArithmeticOperators: true },
288
+ ],
289
+ }),
290
+ },
291
+ ] satisfies FlatConfig[];
292
+ ```
293
+
294
+ ### TypeScript Configuration Files
295
+
296
+ You can also write your eslint config in `.ts` or `.mts` format, all you need to do is run `npm add -D jiti`.
297
+
298
+ ```tsx
299
+ import {
300
+ eslintConfigForTypeScript,
301
+ eslintConfigForVitest,
302
+ type FlatConfig,
303
+ } from 'eslint-config-typed';
304
+
305
+ const thisDir = import.meta.dirname;
306
+
307
+ export default [
308
+ ...eslintConfigForTypeScript({
309
+ tsconfigRootDir: thisDir,
310
+ tsconfigFileName: './tsconfig.json',
311
+ packageDirs: [thisDir],
312
+ }),
313
+ eslintConfigForVitest(),
314
+ ] satisfies FlatConfig[];
315
+ ```
316
+
317
+ For details, see <https://eslint.org/docs/latest/use/configure/configuration-files#typescript-configuration-files>.
210
318
 
211
319
  ## Configuration Examples
212
320
 
213
321
  ### TypeScript + React Project
214
322
 
215
- ```js
323
+ ```tsx
216
324
  import {
217
- defineConfig,
218
- eslintConfigForTypeScript,
219
- eslintConfigForReact,
220
- eslintConfigForNodeJs,
221
325
  defineKnownRules,
326
+ eslintConfigForNodeJs,
327
+ eslintConfigForReact,
328
+ eslintConfigForTypeScript,
329
+ type FlatConfig,
222
330
  } from 'eslint-config-typed';
223
331
 
224
332
  const thisDir = import.meta.dirname;
225
333
 
226
- export default defineConfig([
227
- { ignores: ['**/dist/**', '**/build/**', '**/.next/**'] },
334
+ export default [
335
+ { ignores: ['**/dist/**', '**/build/**', '**/.next/**', 'public/**'] },
228
336
  ...eslintConfigForTypeScript({
229
337
  tsconfigRootDir: thisDir,
230
338
  tsconfigFileName: './tsconfig.json',
231
339
  packageDirs: [thisDir],
232
340
  }),
233
- eslintConfigForReact(['src/**']),
341
+ ...eslintConfigForReact(['src/**']),
234
342
  eslintConfigForNodeJs(['scripts/**', 'configs/**']),
235
343
  {
236
344
  files: ['scripts/**', 'configs/**'],
237
345
  rules: defineKnownRules({
238
346
  '@typescript-eslint/explicit-function-return-type': 'off',
239
347
  'no-await-in-loop': 'off',
240
- 'import/no-unassigned-import': 'off',
241
- 'import/no-internal-modules': 'off',
242
- 'import/no-default-export': 'off',
243
- 'import/no-extraneous-dependencies': 'off',
348
+ 'import-x/no-unassigned-import': 'off',
349
+ 'import-x/no-internal-modules': 'off',
350
+ 'import-x/no-default-export': 'off',
351
+ 'import-x/no-extraneous-dependencies': 'off',
244
352
  }),
245
353
  },
246
- ]);
354
+ ] satisfies FlatConfig[];
247
355
  ```
248
356
 
249
357
  ### Node.js TypeScript Project
250
358
 
251
- ```js
359
+ ```tsx
252
360
  import {
253
- defineConfig,
254
- eslintConfigForTypeScript,
255
- eslintConfigForNodeJs,
256
361
  defineKnownRules,
362
+ eslintConfigForNodeJs,
363
+ eslintConfigForTypeScript,
364
+ type FlatConfig,
257
365
  } from 'eslint-config-typed';
258
366
 
259
- export default defineConfig([
367
+ export default [
260
368
  { ignores: ['**/dist/**', '**/node_modules/**'] },
261
369
  ...eslintConfigForTypeScript({
262
370
  tsconfigRootDir: import.meta.dirname,
@@ -268,25 +376,23 @@ export default defineConfig([
268
376
  rules: defineKnownRules({
269
377
  // Allow console in Node.js
270
378
  'no-console': 'off',
271
- // Allow process.env access
272
- 'no-process-env': 'off',
273
379
  }),
274
380
  },
275
- ]);
381
+ ] satisfies FlatConfig[];
276
382
  ```
277
383
 
278
384
  ### React + Testing Libraries
279
385
 
280
- ```js
386
+ ```tsx
281
387
  import {
282
- defineConfig,
283
- eslintConfigForTypeScript,
284
388
  eslintConfigForReact,
285
- eslintConfigForVitest,
286
389
  eslintConfigForTestingLibrary,
390
+ eslintConfigForTypeScript,
391
+ eslintConfigForVitest,
392
+ type FlatConfig,
287
393
  } from 'eslint-config-typed';
288
394
 
289
- export default defineConfig([
395
+ export default [
290
396
  { ignores: ['**/dist/**', '**/coverage/**'] },
291
397
  ...eslintConfigForTypeScript({
292
398
  tsconfigRootDir: import.meta.dirname,
@@ -296,7 +402,7 @@ export default defineConfig([
296
402
  ...eslintConfigForReact(),
297
403
  eslintConfigForVitest(),
298
404
  eslintConfigForTestingLibrary(),
299
- ]);
405
+ ] satisfies FlatConfig[];
300
406
  ```
301
407
 
302
408
  ## VS Code Integration
@@ -310,36 +416,13 @@ Add the following to `.vscode/settings.json` for proper ESLint integration:
310
416
  "mode": "auto"
311
417
  }
312
418
  ],
313
- "eslint.experimental.useFlatConfig": true,
314
- "editor.codeActionsOnSave": {
315
- "source.fixAll.eslint": "explicit"
316
- }
419
+ "eslint.experimental.useFlatConfig": true
420
+ // "editor.codeActionsOnSave": {
421
+ // "source.fixAll.eslint": "explicit"
422
+ // }
317
423
  }
318
424
  ```
319
425
 
320
- ## TypeScript Configuration Files
321
-
322
- You can also write your eslint config in `.ts` or `.mts` format, all you need to do is run `npm add -D jiti`.
323
-
324
- ```ts
325
- import {
326
- eslintConfigForTypeScript,
327
- eslintConfigForVitest,
328
- type FlatConfig,
329
- } from 'eslint-config-typed';
330
-
331
- export default [
332
- ...eslintConfigForTypeScript({
333
- tsconfigRootDir: thisDir,
334
- tsconfigFileName: './tsconfig.json',
335
- packageDirs: [thisDir],
336
- }),
337
- eslintConfigForVitest(),
338
- ] satisfies FlatConfig[];
339
- ```
340
-
341
- For details, see <https://eslint.org/docs/latest/use/configure/configuration-files#typescript-configuration-files>.
342
-
343
426
  ## Included plugins
344
427
 
345
428
  - @typescript-eslint/eslint-plugin
@@ -351,7 +434,7 @@ For details, see <https://eslint.org/docs/latest/use/configure/configuration-fil
351
434
  - eslint-plugin-sort-destructure-keys
352
435
  - eslint-plugin-security
353
436
  - eslint-plugin-promise
354
- - eslint-plugin-import
437
+ - eslint-plugin-import-x
355
438
  - eslint-plugin-strict-dependencies
356
439
  - eslint-plugin-tree-shakable (Reimplemented in this repository to support flat config)
357
440
  - eslint-plugin-react
@@ -370,7 +453,7 @@ For details, see <https://eslint.org/docs/latest/use/configure/configuration-fil
370
453
 
371
454
  ### Configuration Functions
372
455
 
373
- These functions return arrays of ESLint flat configurations:
456
+ These functions return (arrays of) ESLint flat configuration(s):
374
457
 
375
458
  #### Base Configurations
376
459
 
@@ -385,7 +468,7 @@ These functions return arrays of ESLint flat configurations:
385
468
 
386
469
  - **`eslintConfigForReact(options?)`** - React configuration with hooks and JSX rules
387
470
  - `eslintConfigForBrowser` is included in this configuration
388
- - **`eslintConfigForPreact(options?)`** - Preact configuration (lighter React alternative)
471
+ - **`eslintConfigForPreact(options?)`** - Preact (lighter React alternative) configuration
389
472
  - `eslintConfigForBrowser` is included in this configuration
390
473
  - **`eslintConfigForVitest(options?)`** - Vitest testing framework configuration
391
474
  - **`eslintConfigForJest(options?)`** - Jest testing framework configuration
@@ -412,7 +495,7 @@ Pre-configured rule sets that can be imported and customized:
412
495
  | **`eslintPreferArrowFunctionRules`** | `eslint-plugin-prefer-arrow-functions` | Arrow function preference rules |
413
496
  | **`eslintPluginSortDestructureKeysRules`** | `eslint-plugin-sort-destructure-keys` | Object destructuring rules |
414
497
  | **`eslintPromiseRules`** | `eslint-plugin-promise` | Promise handling rules |
415
- | **`eslintImportsRules`** | `eslint-plugin-import` | Import/export rules |
498
+ | **`eslintImportsRules`** | `eslint-plugin-import-x` | Import/export rules |
416
499
  | **`eslintSecurityRules`** | `eslint-plugin-security` | Security best practices |
417
500
  | **`eslintTreeShakableRules`** | `eslint-plugin-tree-shakable` | Tree-shaking optimization rules |
418
501
  | **`eslintReactRules`** | `eslint-plugin-react` | React-specific rules |
@@ -458,10 +541,14 @@ The shape of the rule option varies depending on the rule, so please check the c
458
541
 
459
542
  Example:
460
543
 
461
- ```js
462
- import { eslintRules } from 'eslint-config-typed';
544
+ ```tsx
545
+ import {
546
+ defineKnownRules,
547
+ eslintRules,
548
+ type FlatConfig,
549
+ } from 'eslint-config-typed';
463
550
 
464
- export default defineConfig([
551
+ export default [
465
552
  // ...
466
553
  {
467
554
  rules: defineKnownRules({
@@ -481,7 +568,7 @@ export default defineConfig([
481
568
  ],
482
569
  }),
483
570
  },
484
- ]);
571
+ ] satisfies FlatConfig[];
485
572
  ```
486
573
 
487
574
  ### Type Definitions
@@ -491,9 +578,13 @@ All rules and configurations come with complete TypeScript type definitions:
491
578
  #### Core Types
492
579
 
493
580
  - **`FlatConfig`** - ESLint flat configuration type
581
+ - `= DeepReadonly<import('@typescript-eslint/utils/ts-eslint').FlatConfig>`
494
582
  - **`ESLintPlugin`** - ESLint plugin type
583
+ - `= DeepReadonly<import('@typescript-eslint/utils/ts-eslint').FlatConfig.Plugin>`
495
584
  - **`Rule`** - ESLint rule definition type
585
+ - `= DeepReadonly<import('@eslint/core').RuleDefinition>`
496
586
  - **`Rules`** - Collection of rules type
587
+ - `= Readonly<Record<string, Rule>>`
497
588
 
498
589
  #### Rule Types
499
590
 
@@ -536,15 +627,27 @@ The pre-configured rules of `eslint-config-typed` are opinionated settings that
536
627
 
537
628
  You can override any rule by adding a configuration object after the preset configurations:
538
629
 
539
- ```js
540
- import { typescriptEslintRules } from 'eslint-config-typed';
630
+ ```tsx
631
+ import {
632
+ defineKnownRules,
633
+ eslintConfigForTypeScript,
634
+ type FlatConfig,
635
+ typescriptEslintRules,
636
+ withDefaultOption,
637
+ } from 'eslint-config-typed';
541
638
 
542
- export default defineConfig([
543
- ...eslintConfigForTypeScript(options),
639
+ const thisDir = import.meta.dirname;
640
+
641
+ export default [
642
+ ...eslintConfigForTypeScript({
643
+ tsconfigRootDir: thisDir,
644
+ tsconfigFileName: './tsconfig.json',
645
+ packageDirs: [thisDir],
646
+ }),
544
647
  {
545
648
  rules: defineKnownRules({
546
649
  // Downgrade to warning (Option settings are inherited)
547
- '@typescript-eslint/no-explicit-any': 'warn',
650
+ '@typescript-eslint/no-explicit-any': withDefaultOption('warn'),
548
651
  // Disable a rule
549
652
  '@typescript-eslint/prefer-readonly-parameter-types': 'off',
550
653
  // Configure with options
@@ -570,19 +673,18 @@ export default defineConfig([
570
673
  ],
571
674
  }),
572
675
  },
573
- ]);
676
+ ] satisfies FlatConfig[];
574
677
  ```
575
678
 
576
- ### Use Type-Safe Rule Options
679
+ ### Use RulesOptions Types
577
680
 
578
681
  Leverage TypeScript for type-safe rule configuration:
579
682
 
580
- ```ts
683
+ ```tsx
581
684
  // configs/restricted-syntax-defs.mjs
582
685
 
583
- import { eslintRules } from 'eslint-config-typed';
686
+ import { eslintRules, type EslintRulesOption } from 'eslint-config-typed';
584
687
 
585
- /** @type {import("eslint-config-typed").EslintRulesOption["no-restricted-syntax"]} */
586
688
  export const restrictedSyntax = [
587
689
  ...eslintRules['no-restricted-syntax'].slice(1),
588
690
  {
@@ -592,31 +694,54 @@ export const restrictedSyntax = [
592
694
  message:
593
695
  'The variable type T should be annotated as `React.useMemo<T>` or `const v: T = React.useMemo(...)`.',
594
696
  },
595
- ];
697
+ ] satisfies EslintRulesOption['no-restricted-syntax'];
596
698
  ```
597
699
 
598
- ```ts
599
- // eslint.config.js
700
+ ```tsx
701
+ // eslint.config.mts
702
+
703
+ import {
704
+ defineKnownRules,
705
+ eslintConfigForTypeScript,
706
+ type FlatConfig,
707
+ } from 'eslint-config-typed';
708
+ import { restrictedSyntax } from './restricted-syntax-defs.mjs';
600
709
 
601
- import { restrictedSyntax } from './configs/restricted-syntax-defs.mjs';
710
+ const thisDir = import.meta.dirname;
602
711
 
603
- export default defineConfig([
604
- ...eslintConfigForTypeScript(options),
712
+ export default [
713
+ ...eslintConfigForTypeScript({
714
+ tsconfigRootDir: thisDir,
715
+ tsconfigFileName: './tsconfig.json',
716
+ packageDirs: [thisDir],
717
+ }),
605
718
  {
606
719
  rules: defineKnownRules({
607
- 'no-restricted-syntax': ['error', restrictedSyntax],
720
+ 'no-restricted-syntax': ['error', ...restrictedSyntax],
608
721
  }),
609
722
  },
610
- ]);
723
+ ] satisfies readonly FlatConfig[];
611
724
  ```
612
725
 
613
726
  ### Target Specific Files
614
727
 
615
728
  Apply different rules to different file patterns:
616
729
 
617
- ```js
618
- export default defineConfig([
619
- ...eslintConfigForTypeScript(options),
730
+ ```tsx
731
+ import {
732
+ defineKnownRules,
733
+ eslintConfigForTypeScript,
734
+ type FlatConfig,
735
+ } from 'eslint-config-typed';
736
+
737
+ const thisDir = import.meta.dirname;
738
+
739
+ export default [
740
+ ...eslintConfigForTypeScript({
741
+ tsconfigRootDir: thisDir,
742
+ tsconfigFileName: './tsconfig.json',
743
+ packageDirs: [thisDir],
744
+ }),
620
745
  {
621
746
  files: ['**/*.test.ts', '**/*.spec.ts'],
622
747
  rules: defineKnownRules({
@@ -631,10 +756,10 @@ export default defineConfig([
631
756
  rules: defineKnownRules({
632
757
  // Allow console in scripts
633
758
  'no-await-in-loop': 'off',
634
- 'import/no-unassigned-import': 'off',
759
+ 'import-x/no-unassigned-import': 'off',
635
760
  }),
636
761
  },
637
- ]);
762
+ ] satisfies FlatConfig[];
638
763
  ```
639
764
 
640
765
  ## Troubleshooting
@@ -645,33 +770,41 @@ export default defineConfig([
645
770
 
646
771
  Ensure the paths are correct:
647
772
 
648
- ```js
773
+ ```tsx
774
+ import {
775
+ eslintConfigForTypeScript,
776
+ type FlatConfig,
777
+ } from 'eslint-config-typed';
778
+
649
779
  const thisDir = import.meta.dirname;
650
780
 
651
- export default defineConfig([
652
- ...eslintConfigForTypeScript({
653
- tsconfigRootDir: thisDir, // Must be absolute path
654
- tsconfigFileName: './tsconfig.json', // Relative to tsconfigRootDir
655
- packageDirs: [thisDir],
656
- }),
657
- ]);
781
+ export default eslintConfigForTypeScript({
782
+ tsconfigRootDir: thisDir, // Must be absolute path
783
+ tsconfigFileName: './tsconfig.json', // Relative to tsconfigRootDir
784
+ packageDirs: [thisDir],
785
+ }) satisfies readonly FlatConfig[];
658
786
  ```
659
787
 
660
788
  #### 2. Import resolution errors
661
789
 
662
790
  The `packageDirs` option helps ESLint resolve imports correctly in monorepos:
663
791
 
664
- ```js
665
- export default defineConfig([
666
- ...eslintConfigForTypeScript({
667
- tsconfigRootDir: thisDir,
668
- tsconfigFileName: './tsconfig.json',
669
- packageDirs: [
670
- path.resolve(thisDir, '../../..'), // Monorepo root
671
- thisDir, // Current package
672
- ],
673
- }),
674
- ]);
792
+ ```tsx
793
+ import {
794
+ eslintConfigForTypeScript,
795
+ type FlatConfig,
796
+ } from 'eslint-config-typed';
797
+
798
+ const thisDir = import.meta.dirname;
799
+
800
+ export default eslintConfigForTypeScript({
801
+ tsconfigRootDir: thisDir,
802
+ tsconfigFileName: './tsconfig.json',
803
+ packageDirs: [
804
+ path.resolve(thisDir, '../../..'), // Monorepo root
805
+ thisDir, // Current package
806
+ ],
807
+ }) satisfies readonly FlatConfig[];
675
808
  ```
676
809
 
677
810
  #### 3. Performance issues
@@ -685,9 +818,36 @@ For large projects, consider:
685
818
  - Running ESLint with `--cache` flag
686
819
  - Limiting the scope of type-aware rules
687
820
 
821
+ #### 4. How to Use import-x/no-unused-modules
822
+
823
+ [`import-x/no-unused-modules`](https://github.com/un-ts/eslint-plugin-import-x/blob/v4.16.1/docs/rules/no-unused-modules.md) reports exported values that are never imported anywhere else. The rule still relies on ESLint’s classic configuration loader to discover ignore patterns, so a flat-config-only setup is not enough. For this to work, you need to place a `.eslintrc.cjs` file along with `eslint.config.mts`.
824
+
825
+ ```cjs
826
+ // .eslintrc.cjs
827
+ module.exports = {
828
+ ignorePatterns: ['**/node_modules/**', 'dist', '.eslintrc.cjs'],
829
+ };
830
+ ```
831
+
832
+ The flat config then enables the rule for our source tree and marks the public federation module as an allowed unused export:
833
+
834
+ ```ts
835
+ // eslint.config.mts (excerpt)
836
+ {
837
+ files: ['src/**'],
838
+ rules: defineKnownRules({
839
+ 'import-x/no-unused-modules': [
840
+ 'error',
841
+ { unusedExports: true, ignoreExports: ['src/entry-point.mts'] },
842
+ ],
843
+ }),
844
+ },
845
+ ```
846
+
847
+ With this configuration, you can run eslint and receive actionable diagnostic information when exports are no longer referenced. If you implement a library, add the file paths that define the variables, types, etc. that your library exports to the `ignoreExports` array so that the rule does not flag intentionally re-exported surfaces.
848
+
688
849
  ### Known Limitations
689
850
 
690
- - The `import/no-unused-modules` rule does not function properly with Native ESM
691
851
  - Some type-aware rules may have performance impacts on very large codebases
692
852
  - Flat config requires ESLint 9.0+ and may not be compatible with older tools
693
853