eslint-plugin-nextfriday 4.3.2 → 5.0.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,43 @@
1
1
  # eslint-plugin-nextfriday
2
2
 
3
+ ## 5.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - [#136](https://github.com/next-friday/eslint-plugin-nextfriday/pull/136) [`d5dd064`](https://github.com/next-friday/eslint-plugin-nextfriday/commit/d5dd064c4de84ef90cc67cbb914e31288b13afab) Thanks [@joetakara](https://github.com/joetakara)! - fix `index-export-only` to allow string directive prologues (e.g. `"use strict"`) in index files — previously flagged as disallowed expression statements
8
+
9
+ fix `sort-imports` group ordering — `import type` now belongs to the same group as its source (external type after external value, internal alias type after internal alias value, etc.) and relative imports are split into parent (`../`) and current (`./`) sub-groups
10
+
11
+ fix `sort-imports` `checkOrder` return type — early-return now yields `false` instead of `undefined`, satisfying the declared `boolean` return type
12
+
13
+ remove `no-inline-default-export` rule — the rule conflicts with framework route handler patterns that require inline named function exports (`export async function GET`)
14
+
15
+ remove `no-nested-ternary` rule — duplicates ESLint's built-in `no-nested-ternary` with identical behavior; use the built-in rule directly instead
16
+
17
+ remove `enforce-property-case` rule — duplicates ESLint's built-in `camelcase` with `{ properties: "always" }`; use the built-in rule directly instead
18
+
19
+ remove `no-single-char-variables` rule — duplicates ESLint's built-in `id-length` with `{ min: 2, exceptions: ["_", "i", "j", "k", "n"] }`; use the built-in rule directly instead
20
+
21
+ remove `prefer-function-declaration` rule — duplicates ESLint's built-in `func-style` with `["declaration", { allowArrowFunctions: false }]`; use the built-in rule directly instead
22
+
23
+ remove `enforce-camel-case` rule — duplicates ESLint's built-in `camelcase`; use the built-in rule directly instead
24
+
25
+ remove `prefer-jsx-template-literals` rule — duplicates ESLint's built-in `prefer-template` with broader coverage; use the built-in rule directly instead
26
+
27
+ remove `no-redundant-fragment` rule — duplicates `eslint-plugin-react`'s `react/jsx-no-useless-fragment` with identical behavior; use the plugin rule directly instead
28
+
29
+ remove `react-props-destructure` rule — duplicates `eslint-plugin-react`'s `react/destructuring-assignment` with `["error", "always"]`; use the plugin rule directly instead
30
+
31
+ ## 4.4.0
32
+
33
+ ### Minor Changes
34
+
35
+ - [#134](https://github.com/next-friday/eslint-plugin-nextfriday/pull/134) [`ae95cb8`](https://github.com/next-friday/eslint-plugin-nextfriday/commit/ae95cb840eb5e1a2f342e58958e0a44a94d4ae3d) Thanks [@joetakara](https://github.com/joetakara)! - remove `prefer-inline-type-export` rule
36
+
37
+ fix `prefer-import-type` incorrectly converting namespace imports used as JSX member expressions (e.g. `<Avatar.Root>`) to `import type`
38
+
39
+ update `prefer-props-with-children` to only flag optional `children?: ReactNode` — required `children: ReactNode` is no longer reported
40
+
3
41
  ## 4.3.2
4
42
 
5
43
  ### Patch Changes
package/README.md CHANGED
@@ -50,7 +50,7 @@ export default [nextfriday.configs["nextjs/recommended"]];
50
50
 
51
51
  To use a preset and adjust individual rules, append a second config object after the preset. Later objects override earlier ones, so you can change severity, swap options, or add rules without re-declaring the entire preset.
52
52
 
53
- For example, start with the `react/recommended` preset (which runs `nextfriday/enforce-camel-case` and `nextfriday/enforce-props-suffix` as errors) and add a rule override on top:
53
+ For example, start with the `react/recommended` preset (which runs `nextfriday/enforce-constant-case` and `nextfriday/enforce-props-suffix` as errors) and add a rule override on top:
54
54
 
55
55
  ```js
56
56
  import nextfriday from "eslint-plugin-nextfriday";
@@ -99,18 +99,14 @@ export default [
99
99
  },
100
100
  rules: {
101
101
  // Variable Naming
102
- "nextfriday/no-single-char-variables": "error",
103
102
  "nextfriday/no-lazy-identifiers": "error",
104
103
  "nextfriday/boolean-naming-prefix": "error",
105
- "nextfriday/enforce-camel-case": "error",
106
104
  "nextfriday/enforce-constant-case": "error",
107
- "nextfriday/enforce-property-case": "error",
108
105
  "nextfriday/no-misleading-constant-case": "error",
109
106
 
110
107
  // Code Style
111
108
  "nextfriday/no-emoji": "error",
112
109
  "nextfriday/prefer-destructuring-params": "error",
113
- "nextfriday/prefer-function-declaration": "error",
114
110
  "nextfriday/require-explicit-return-type": "error",
115
111
  "nextfriday/no-complex-inline-return": "error",
116
112
  "nextfriday/no-logic-in-params": "error",
@@ -125,7 +121,6 @@ export default [
125
121
  "nextfriday/no-inline-nested-object": "error",
126
122
  "nextfriday/no-inline-return-properties": "error",
127
123
  "nextfriday/prefer-async-await": "error",
128
- "nextfriday/no-nested-ternary": "error",
129
124
  "nextfriday/prefer-guard-clause": "error",
130
125
 
131
126
  // Import Optimization
@@ -156,8 +151,6 @@ export default [
156
151
  "nextfriday/jsx-simple-props": "error",
157
152
  "nextfriday/jsx-sort-props": "error",
158
153
  "nextfriday/jsx-spread-props-last": "error",
159
- "nextfriday/prefer-jsx-template-literals": "error",
160
- "nextfriday/react-props-destructure": "error",
161
154
  "nextfriday/enforce-props-suffix": "error",
162
155
  "nextfriday/enforce-readonly-component-props": "error",
163
156
  },
@@ -208,7 +201,6 @@ export default [
208
201
  files: ["**/*.{test,spec}.{ts,tsx}"],
209
202
  rules: {
210
203
  "nextfriday/require-explicit-return-type": "off",
211
- "nextfriday/no-single-char-variables": "off",
212
204
  "nextfriday/no-direct-date": "off",
213
205
  },
214
206
  },
@@ -335,7 +327,6 @@ export default [
335
327
  files: ["src/legacy/**/*.{ts,tsx}"],
336
328
  rules: {
337
329
  "nextfriday/no-relative-imports": "off",
338
- "nextfriday/enforce-camel-case": "off",
339
330
  },
340
331
  },
341
332
  ];
@@ -382,7 +373,7 @@ When the warn-level preset surfaces hundreds of violations, fix them in this ord
382
373
  | Tier | Examples | Why first |
383
374
  | ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
384
375
  | High — correctness and runtime safety | `no-direct-date`, `no-env-fallback`, `enforce-readonly-component-props`, `jsx-no-non-component-function`, `enforce-hook-naming`, `no-logic-in-params` | Each violation can mask a bug, leak config, or break React's rules of hooks. Fix before they ship. |
385
- | Medium — structure and naming | `boolean-naming-prefix`, `enforce-camel-case`, `enforce-constant-case`, `enforce-props-suffix`, `prefer-import-type` | No runtime impact, but inconsistent naming compounds review and onboarding cost. Fix once the high tier is clean. |
376
+ | Medium — structure and naming | `boolean-naming-prefix`, `enforce-constant-case`, `enforce-props-suffix`, `prefer-import-type` | No runtime impact, but inconsistent naming compounds review and onboarding cost. Fix once the high tier is clean. |
386
377
  | Low — formatting and ordering | `sort-imports`, `sort-exports`, `sort-type-alphabetically`, `jsx-sort-props`, `newline-before-return`, `newline-after-multiline-block`, `no-emoji` | Cosmetic. Most are auto-fixable, so a single `pnpm eslint --fix` pass typically clears the whole codebase. Save these for last. |
387
378
 
388
379
  In practice: turn the high tier on as `"error"` first, leave the medium tier as `"warn"` while you migrate, and run the auto-fixers for the low tier in a single dedicated PR.
@@ -395,12 +386,9 @@ In practice: turn the high tier on as `"error"` first, leave the medium tier as
395
386
 
396
387
  | Rule | Description | Fixable |
397
388
  | ------------------------------------------------------------------------ | --------------------------------------------------------------------- | ------- |
398
- | [no-single-char-variables](docs/rules/NO_SINGLE_CHAR_VARIABLES.md) | Disallow single character variable names (e.g., `d`, `u`, `l`) | ❌ |
399
389
  | [no-lazy-identifiers](docs/rules/NO_LAZY_IDENTIFIERS.md) | Disallow lazy identifiers like `xxx`, `asdf`, `qwerty` | ❌ |
400
390
  | [boolean-naming-prefix](docs/rules/BOOLEAN_NAMING_PREFIX.md) | Enforce boolean variables to have prefix (is, has, should, can, etc.) | ❌ |
401
- | [enforce-camel-case](docs/rules/ENFORCE_CAMEL_CASE.md) | Ban snake_case and restrict PascalCase to React components | ❌ |
402
391
  | [enforce-constant-case](docs/rules/ENFORCE_CONSTANT_CASE.md) | Enforce SCREAMING_SNAKE_CASE for global static constant values | ❌ |
403
- | [enforce-property-case](docs/rules/ENFORCE_PROPERTY_CASE.md) | Enforce camelCase for unquoted object property keys | ❌ |
404
392
  | [no-misleading-constant-case](docs/rules/NO_MISLEADING_CONSTANT_CASE.md) | Disallow SCREAMING_SNAKE_CASE in local scope and for dynamic values | ❌ |
405
393
 
406
394
  ### Code Style Rules
@@ -409,7 +397,6 @@ In practice: turn the high tier on as `"error"` first, leave the medium tier as
409
397
  | ---------------------------------------------------------------------------- | ---------------------------------------------------------------------- | ------- |
410
398
  | [no-emoji](docs/rules/NO_EMOJI.md) | Disallow emoji characters in source code | ❌ |
411
399
  | [prefer-destructuring-params](docs/rules/PREFER_DESTRUCTURING_PARAMS.md) | Enforce destructuring for functions with multiple parameters | ❌ |
412
- | [prefer-function-declaration](docs/rules/PREFER_FUNCTION_DECLARATION.md) | Enforce function declarations over arrow functions in .ts files | ❌ |
413
400
  | [require-explicit-return-type](docs/rules/REQUIRE_EXPLICIT_RETURN_TYPE.md) | Require explicit return types on functions for better documentation | ❌ |
414
401
  | [no-complex-inline-return](docs/rules/NO_COMPLEX_INLINE_RETURN.md) | Disallow complex inline expressions in return - extract to const first | ❌ |
415
402
  | [no-logic-in-params](docs/rules/NO_LOGIC_IN_PARAMS.md) | Disallow logic/conditions in function parameters - extract to const | ❌ |
@@ -419,7 +406,6 @@ In practice: turn the high tier on as `"error"` first, leave the medium tier as
419
406
  | [enforce-service-naming](docs/rules/ENFORCE_SERVICE_NAMING.md) | Enforce 'fetch' prefix for async functions in \*.service.ts files | ❌ |
420
407
  | [enforce-sorted-destructuring](docs/rules/ENFORCE_SORTED_DESTRUCTURING.md) | Enforce alphabetical sorting of destructured properties | ✅ |
421
408
  | [no-env-fallback](docs/rules/NO_ENV_FALLBACK.md) | Disallow fallback values for environment variables | ❌ |
422
- | [no-inline-default-export](docs/rules/NO_INLINE_DEFAULT_EXPORT.md) | Disallow inline default exports - declare first, then export | ❌ |
423
409
  | [index-export-only](docs/rules/INDEX_EXPORT_ONLY.md) | Restrict index files to imports, re-exports, and type declarations | ❌ |
424
410
  | [no-direct-date](docs/rules/NO_DIRECT_DATE.md) | Disallow direct usage of Date constructor and methods | ❌ |
425
411
  | [newline-after-multiline-block](docs/rules/NEWLINE_AFTER_MULTILINE_BLOCK.md) | Require a blank line after multi-line statements | ✅ |
@@ -427,7 +413,6 @@ In practice: turn the high tier on as `"error"` first, leave the medium tier as
427
413
  | [no-inline-nested-object](docs/rules/NO_INLINE_NESTED_OBJECT.md) | Require nested objects and arrays to span multiple lines | ✅ |
428
414
  | [no-inline-return-properties](docs/rules/NO_INLINE_RETURN_PROPERTIES.md) | Require return object properties to use shorthand notation | ❌ |
429
415
  | [prefer-async-await](docs/rules/PREFER_ASYNC_AWAIT.md) | Enforce async/await over .then() promise chains | ❌ |
430
- | [no-nested-ternary](docs/rules/NO_NESTED_TERNARY.md) | Disallow nested ternary expressions | ❌ |
431
416
  | [prefer-guard-clause](docs/rules/PREFER_GUARD_CLAUSE.md) | Enforce guard clause pattern instead of nested if statements | ❌ |
432
417
  | [no-helper-function-in-hook](docs/rules/NO_HELPER_FUNCTION_IN_HOOK.md) | Disallow non-hook helper function definitions in hook files | ❌ |
433
418
  | [no-helper-function-in-test](docs/rules/NO_HELPER_FUNCTION_IN_TEST.md) | Disallow helper function definitions in test files | ❌ |
@@ -451,7 +436,6 @@ In practice: turn the high tier on as `"error"` first, leave the medium tier as
451
436
  | [no-nested-interface-declaration](docs/rules/NO_NESTED_INTERFACE_DECLARATION.md) | Disallow inline object types in interface/type properties | ❌ |
452
437
  | [prefer-named-param-types](docs/rules/PREFER_NAMED_PARAM_TYPES.md) | Enforce named types for function parameters with object types | ❌ |
453
438
  | [prefer-inline-literal-union](docs/rules/PREFER_INLINE_LITERAL_UNION.md) | Enforce inlining literal union types for better IDE hover info | ✅ |
454
- | [prefer-inline-type-export](docs/rules/PREFER_INLINE_TYPE_EXPORT.md) | Require type/interface exports inline at the declaration | ✅ |
455
439
  | [prefer-interface-for-component-props](docs/rules/PREFER_INTERFACE_FOR_COMPONENT_PROPS.md) | Enforce interface over type alias for component prop declarations | ✅ |
456
440
  | [prefer-interface-over-inline-types](docs/rules/PREFER_INTERFACE_OVER_INLINE_TYPES.md) | Enforce interface declarations over inline types for React props | ❌ |
457
441
  | [sort-type-alphabetically](docs/rules/SORT_TYPE_ALPHABETICALLY.md) | Enforce A-Z sorting of properties within type groups | ✅ |
@@ -475,10 +459,7 @@ In practice: turn the high tier on as `"error"` first, leave the medium tier as
475
459
  | [jsx-sort-props](docs/rules/JSX_SORT_PROPS.md) | Enforce JSX props are sorted by value type | ✅ |
476
460
  | [jsx-spread-props-last](docs/rules/JSX_SPREAD_PROPS_LAST.md) | Enforce JSX spread attributes appear after all other props | ❌ |
477
461
  | [no-ghost-wrapper](docs/rules/NO_GHOST_WRAPPER.md) | Disallow bare `<div>`/`<span>` with no meaningful attributes | ❌ |
478
- | [no-redundant-fragment](docs/rules/NO_REDUNDANT_FRAGMENT.md) | Disallow Fragments wrapping zero or one child | ❌ |
479
- | [prefer-jsx-template-literals](docs/rules/PREFER_JSX_TEMPLATE_LITERALS.md) | Enforce template literals instead of mixing text and JSX expressions | ✅ |
480
462
  | [prefer-props-with-children](docs/rules/PREFER_PROPS_WITH_CHILDREN.md) | Prefer PropsWithChildren over manually declaring children: ReactNode | ❌ |
481
- | [react-props-destructure](docs/rules/REACT_PROPS_DESTRUCTURE.md) | Enforce destructuring props inside React component body | ❌ |
482
463
  | [enforce-props-suffix](docs/rules/ENFORCE_PROPS_SUFFIX.md) | Enforce 'Props' suffix for interfaces and types in \*.tsx files | ❌ |
483
464
  | [enforce-readonly-component-props](docs/rules/ENFORCE_READONLY_COMPONENT_PROPS.md) | Enforce Readonly wrapper for React component props | ✅ |
484
465
  | [enforce-render-naming](docs/rules/ENFORCE_RENDER_NAMING.md) | Enforce 'render' prefix for variables holding JSX inside components | ❌ |
@@ -489,26 +470,24 @@ In practice: turn the high tier on as `"error"` first, leave the medium tier as
489
470
 
490
471
  | Preset | Severity | Base Rules | JSX Rules | Total Rules |
491
472
  | -------------------- | -------- | ---------- | --------- | ----------- |
492
- | `base` | warn | 42 | 0 | 42 |
493
- | `base/recommended` | error | 42 | 0 | 42 |
494
- | `react` | warn | 42 | 23 | 65 |
495
- | `react/recommended` | error | 42 | 23 | 65 |
496
- | `nextjs` | warn | 42 | 23 | 65 |
497
- | `nextjs/recommended` | error | 42 | 23 | 65 |
473
+ | `base` | warn | 43 | 0 | 43 |
474
+ | `base/recommended` | error | 43 | 0 | 43 |
475
+ | `react` | warn | 43 | 23 | 66 |
476
+ | `react/recommended` | error | 43 | 23 | 66 |
477
+ | `nextjs` | warn | 43 | 23 | 66 |
478
+ | `nextjs/recommended` | error | 43 | 23 | 66 |
498
479
 
499
480
  The `nextjs` and `nextjs/recommended` presets currently share the same rule set as `react` and `react/recommended`; they are kept as named aliases for ergonomics.
500
481
 
501
- ### Base Configuration Rules (42 rules)
482
+ ### Base Configuration Rules (43 rules)
502
483
 
503
484
  Included in `base`, `base/recommended`, and all other presets:
504
485
 
505
486
  - `nextfriday/boolean-naming-prefix`
506
- - `nextfriday/enforce-camel-case`
507
487
  - `nextfriday/enforce-constant-case`
508
488
  - `nextfriday/enforce-hook-filename`
509
489
  - `nextfriday/enforce-hook-naming`
510
490
  - `nextfriday/enforce-test-filename`
511
- - `nextfriday/enforce-property-case`
512
491
  - `nextfriday/enforce-service-naming`
513
492
  - `nextfriday/enforce-sorted-destructuring`
514
493
  - `nextfriday/enforce-type-declaration-order`
@@ -519,7 +498,6 @@ Included in `base`, `base/recommended`, and all other presets:
519
498
  - `nextfriday/no-direct-date`
520
499
  - `nextfriday/no-emoji`
521
500
  - `nextfriday/no-env-fallback`
522
- - `nextfriday/no-inline-default-export`
523
501
  - `nextfriday/no-inline-nested-object`
524
502
  - `nextfriday/no-inline-return-properties`
525
503
  - `nextfriday/no-inline-type-import`
@@ -527,16 +505,12 @@ Included in `base`, `base/recommended`, and all other presets:
527
505
  - `nextfriday/no-logic-in-params`
528
506
  - `nextfriday/no-misleading-constant-case`
529
507
  - `nextfriday/no-nested-interface-declaration`
530
- - `nextfriday/no-nested-ternary`
531
508
  - `nextfriday/no-relative-imports`
532
- - `nextfriday/no-single-char-variables`
533
509
  - `nextfriday/prefer-async-await`
534
510
  - `nextfriday/prefer-destructuring-params`
535
- - `nextfriday/prefer-function-declaration`
536
511
  - `nextfriday/prefer-guard-clause`
537
512
  - `nextfriday/prefer-import-type`
538
513
  - `nextfriday/prefer-inline-literal-union`
539
- - `nextfriday/prefer-inline-type-export`
540
514
  - `nextfriday/prefer-named-param-types`
541
515
  - `nextfriday/prefer-react-import-types`
542
516
  - `nextfriday/require-explicit-return-type`
@@ -566,12 +540,9 @@ Additionally included in `react`, `react/recommended`, `nextjs`, `nextjs/recomme
566
540
  - `nextfriday/jsx-sort-props`
567
541
  - `nextfriday/jsx-spread-props-last`
568
542
  - `nextfriday/no-ghost-wrapper`
569
- - `nextfriday/no-redundant-fragment`
570
543
  - `nextfriday/prefer-interface-for-component-props`
571
544
  - `nextfriday/prefer-interface-over-inline-types`
572
- - `nextfriday/prefer-jsx-template-literals`
573
545
  - `nextfriday/prefer-props-with-children`
574
- - `nextfriday/react-props-destructure`
575
546
 
576
547
  ### Severity Levels
577
548
 
@@ -101,5 +101,4 @@ If you need stricter coverage of object/class members, pair this rule with [`@ty
101
101
 
102
102
  ## Related Rules
103
103
 
104
- - [no-single-char-variables](./NO_SINGLE_CHAR_VARIABLES.md) - Disallows single character variable names
105
104
  - [@typescript-eslint/naming-convention](https://typescript-eslint.io/rules/naming-convention/) - More comprehensive naming convention rule
@@ -109,7 +109,6 @@ export default [
109
109
  rules: {
110
110
  "nextfriday/enforce-constant-case": "error",
111
111
  "nextfriday/no-misleading-constant-case": "error",
112
- "nextfriday/enforce-camel-case": "error",
113
112
  },
114
113
  },
115
114
  ];
@@ -166,4 +165,3 @@ This plugin only supports ESLint 9+ flat config — legacy `.eslintrc` is not su
166
165
  ## Related Rules
167
166
 
168
167
  - [no-misleading-constant-case](NO_MISLEADING_CONSTANT_CASE.md) - Disallows SCREAMING_SNAKE_CASE in local scope and for dynamic values
169
- - [enforce-camel-case](ENFORCE_CAMEL_CASE.md) - Enforces camelCase for variables and functions
@@ -92,4 +92,3 @@ This rule is fixable using ESLint's `--fix` option. The fixer will automatically
92
92
  ## Related Rules
93
93
 
94
94
  - [`prefer-interface-over-inline-types`](./PREFER_INTERFACE_OVER_INLINE_TYPES.md) - Enforces interface declarations over inline types
95
- - [`react-props-destructure`](./REACT_PROPS_DESTRUCTURE.md) - Enforces destructuring props inside component body
@@ -43,6 +43,12 @@ console.log("loaded");
43
43
 
44
44
  ### Correct
45
45
 
46
+ ```ts
47
+ "use strict";
48
+
49
+ export { cn } from "./cn";
50
+ ```
51
+
46
52
  ```ts
47
53
  export { cn } from "./cn";
48
54
  export * from "./types";
@@ -66,6 +72,7 @@ export interface Bar {
66
72
  ## What This Rule Allows
67
73
 
68
74
  - `import` statements (including side-effect imports like `import "./styles.css"`)
75
+ - String directive prologues (e.g. `"use strict"`)
69
76
  - Specifier-only `export` and `export ... from` re-exports
70
77
  - `export *` and `export * as ns` re-exports
71
78
  - `export default identifier` where the identifier comes from an import
@@ -69,7 +69,3 @@ Any of the following attributes count as meaningful and silence the rule:
69
69
  ## When Not To Use It
70
70
 
71
71
  If your codebase intentionally uses bare `<div>` and `<span>` as structural placeholders, or if you rely on parent CSS selectors that target a fixed wrapper depth.
72
-
73
- ## Related Rules
74
-
75
- - [no-redundant-fragment](NO_REDUNDANT_FRAGMENT.md)
@@ -78,7 +78,7 @@ Variables containing 4 or more consecutive keyboard row characters:
78
78
 
79
79
  ### Short Identifiers
80
80
 
81
- Identifiers shorter than 3 characters are ignored (use `no-single-char-variables` for those).
81
+ Identifiers shorter than 3 characters are ignored (use the core ESLint `id-length` rule with `min: 2` for those).
82
82
 
83
83
  ### Underscore-Prefixed
84
84
 
@@ -95,5 +95,4 @@ const _unused = getValue();
95
95
 
96
96
  ## Related Rules
97
97
 
98
- - [no-single-char-variables](./NO_SINGLE_CHAR_VARIABLES.md) - Disallows single character variable names
99
98
  - [boolean-naming-prefix](./BOOLEAN_NAMING_PREFIX.md) - Enforces naming conventions for boolean variables
@@ -73,4 +73,3 @@ If your project does not follow the convention that SCREAMING_SNAKE_CASE is rese
73
73
  ## Related Rules
74
74
 
75
75
  - [enforce-constant-case](ENFORCE_CONSTANT_CASE.md) - The complementary rule that enforces SCREAMING_SNAKE_CASE for global static constants
76
- - [enforce-camel-case](ENFORCE_CAMEL_CASE.md) - Enforces camelCase for variables and functions
@@ -1,36 +1,24 @@
1
1
  # prefer-props-with-children
2
2
 
3
- Prefer `PropsWithChildren<T>` over manually declaring `children: ReactNode` in component props.
3
+ Prefer `PropsWithChildren<T>` over manually declaring `children?: ReactNode` in component props.
4
4
 
5
5
  ## Rule Details
6
6
 
7
- This rule reports interfaces, type aliases, and inline parameter types that declare a `children` field typed as `ReactNode` (or `React.ReactNode`). React already provides the `PropsWithChildren<T>` helper for this exact case, so prefer it for consistency and to avoid restating the well-known `children` shape on every component.
7
+ This rule reports interfaces, type aliases, and inline parameter types that declare an **optional** `children` field typed as `ReactNode` (or `React.ReactNode`). `PropsWithChildren<T>` already provides exactly this an optional `children: ReactNode` so the manual declaration is redundant.
8
8
 
9
- The rule only flags `children` whose type is exactly `ReactNode` (matching what `PropsWithChildren` provides). Other shapes such as `ReactElement`, render-prop functions, or unions like `ReactNode | string` are left alone.
9
+ Required `children: ReactNode` (without `?`) is intentional and is not flagged, because `PropsWithChildren` cannot express required children.
10
+
11
+ The rule only flags `children?` whose type is exactly `ReactNode`. Other shapes such as `ReactElement`, render-prop functions, or unions like `ReactNode | string` are left alone.
10
12
 
11
13
  ### Why?
12
14
 
13
- - `PropsWithChildren<T>` is the canonical type for components that accept children, making intent obvious at a glance.
14
- - It eliminates duplication of the `children` declaration across every component that accepts children.
15
- - It keeps the surrounding props focused on what is unique to the component.
15
+ - `PropsWithChildren<T>` is the canonical type for components that optionally accept children, making intent obvious at a glance.
16
+ - Required `children: ReactNode` (no `?`) cannot be replaced by `PropsWithChildren` that case is intentional and not flagged.
16
17
 
17
18
  ## Examples
18
19
 
19
20
  ### Incorrect
20
21
 
21
- ```tsx
22
- interface LayoutProps {
23
- children: ReactNode;
24
- }
25
- ```
26
-
27
- ```tsx
28
- interface CardProps {
29
- title: string;
30
- children: ReactNode;
31
- }
32
- ```
33
-
34
22
  ```tsx
35
23
  interface OptionalChildrenProps {
36
24
  children?: ReactNode;
@@ -39,25 +27,22 @@ interface OptionalChildrenProps {
39
27
  ```
40
28
 
41
29
  ```tsx
42
- interface ReactNamespaceProps {
43
- children: React.ReactNode;
30
+ interface LayoutProps {
31
+ children?: ReactNode;
44
32
  }
45
33
  ```
46
34
 
47
35
  ```tsx
48
36
  type WrapperProps = {
49
- children: ReactNode;
37
+ children?: ReactNode;
50
38
  className: string;
51
39
  };
52
40
  ```
53
41
 
54
42
  ```tsx
55
- const Component = ({ children, label }: { children: ReactNode; label: string }) => (
56
- <div>
57
- {children}
58
- {label}
59
- </div>
60
- );
43
+ interface ReactNamespaceProps {
44
+ children?: React.ReactNode;
45
+ }
61
46
  ```
62
47
 
63
48
  ### Correct
@@ -79,12 +64,9 @@ type WrapperProps = PropsWithChildren<{
79
64
  ```
80
65
 
81
66
  ```tsx
82
- const Component = (props: Readonly<PropsWithChildren<{ label: string }>>) => (
83
- <div>
84
- {props.children}
85
- {props.label}
86
- </div>
87
- );
67
+ interface RequiredChildrenProps {
68
+ children: ReactNode;
69
+ }
88
70
  ```
89
71
 
90
72
  ```tsx
@@ -103,7 +85,7 @@ interface SlotProps {
103
85
 
104
86
  This rule should not be used if:
105
87
 
106
- - Your project intentionally avoids `PropsWithChildren` and prefers explicit `children` declarations.
88
+ - Your project intentionally avoids `PropsWithChildren` and prefers explicit `children?` declarations.
107
89
  - You frequently use children types other than `ReactNode` (this rule already skips those cases).
108
90
 
109
91
  ## Related Rules
@@ -17,12 +17,13 @@ This rule enforces that import statements are grouped and ordered by their sourc
17
17
  ### Import Group Order
18
18
 
19
19
  1. **Side-effect imports** — no specifiers (e.g., `import "./setup"`)
20
- 2. **Node.js builtins** `node:` prefix or known builtin names (e.g., `import fs from "node:fs"`)
21
- 3. **External packages** scoped or plain package names (e.g., `import React from "react"`)
22
- 4. **Internal aliases** — paths starting with `@/`, `~/`, or `#` (e.g., `import { utils } from "@/lib/utils"`)
23
- 5. **Relative imports** — paths starting with `.` (e.g., `import { foo } from "../foo"`)
20
+ 2. **Builtin** value **builtin type**
21
+ 3. **External** value **external type**
22
+ 4. **Internal alias** value → **internal alias type** — paths starting with `@/`, `~/`, or `#`
23
+ 5. **Parent relative** value → **parent relative type** — paths starting with `../` (any depth)
24
+ 6. **Relative** value → **relative type** — paths starting with `./`
24
25
 
25
- Type-only imports (`import type`) are skipped and do not affect ordering.
26
+ Within each group, value imports come first, then `import type` for the same group.
26
27
 
27
28
  Non-contiguous imports (separated by other statements) are checked independently.
28
29
 
@@ -31,7 +32,13 @@ Non-contiguous imports (separated by other statements) are checked independently
31
32
  ### Incorrect
32
33
 
33
34
  ```ts
34
- // Bad: Relative before external
35
+ // Bad: type import before value import in same group
36
+ import type { Foo } from "some-lib";
37
+ import { bar } from "some-lib";
38
+ ```
39
+
40
+ ```ts
41
+ // Bad: relative before external
35
42
  import { foo } from "../foo";
36
43
  import React from "react";
37
44
  ```
@@ -51,19 +58,22 @@ import "./setup";
51
58
  ### Correct
52
59
 
53
60
  ```ts
54
- // Good: All 5 groups in correct order
55
61
  import "./setup";
62
+
56
63
  import fs from "node:fs";
64
+
57
65
  import React from "react";
66
+ import type { FC } from "react";
67
+
58
68
  import { utils } from "@/lib/utils";
59
- import { foo } from "../foo";
60
- ```
69
+ import type { Utils } from "@/lib/utils";
61
70
 
62
- ```ts
63
- // Good: Type imports can appear anywhere
64
- import type { FC } from "react";
65
- import { foo } from "../foo";
66
- import React from "react";
71
+ import { foo } from "../../foo";
72
+ import { bar } from "../bar";
73
+ import type { Bar } from "../bar";
74
+
75
+ import { baz } from "./baz";
76
+ import type { Baz } from "./baz";
67
77
  ```
68
78
 
69
79
  ```ts