eslint-plugin-nextfriday 1.14.0 → 1.15.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,15 @@
1
1
  # eslint-plugin-nextfriday
2
2
 
3
+ ## 1.15.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#68](https://github.com/next-friday/eslint-plugin-nextfriday/pull/68) [`857906e`](https://github.com/next-friday/eslint-plugin-nextfriday/commit/857906e5264ef87a988ba5429019c004360fa2a1) Thanks [@nextfridaydeveloper](https://github.com/nextfridaydeveloper)! - Add sort-imports, sort-exports, sort-type-alphabetically, jsx-sort-props, jsx-no-newline-single-line-elements rules. Add auto-fix to sorting rules. Bundle eslint-plugin-unicorn and eslint-plugin-sonarjs configs.
8
+
9
+ ### Patch Changes
10
+
11
+ - [#69](https://github.com/next-friday/eslint-plugin-nextfriday/pull/69) [`2475fc5`](https://github.com/next-friday/eslint-plugin-nextfriday/commit/2475fc5e7d80c2b158cddbed961dbb7e4e348188) Thanks [@joetakara](https://github.com/joetakara)! - Fix CJS compatibility for bundled eslint-plugin-sonarjs and eslint-plugin-unicorn configs.
12
+
3
13
  ## 1.14.0
4
14
 
5
15
  ### Minor Changes
package/README.md CHANGED
@@ -94,19 +94,24 @@ export default [
94
94
  "nextfriday/no-relative-imports": "error",
95
95
  "nextfriday/prefer-import-type": "error",
96
96
  "nextfriday/prefer-react-import-types": "error",
97
+ "nextfriday/sort-exports": "error",
98
+ "nextfriday/sort-imports": "error",
97
99
 
98
100
  // Type Patterns
99
101
  "nextfriday/prefer-named-param-types": "error",
100
102
  "nextfriday/prefer-interface-over-inline-types": "error",
103
+ "nextfriday/sort-type-alphabetically": "error",
101
104
  "nextfriday/sort-type-required-first": "error",
102
105
 
103
106
  // React/JSX
104
107
  "nextfriday/jsx-newline-between-elements": "error",
105
108
  "nextfriday/jsx-no-inline-object-prop": "error",
109
+ "nextfriday/jsx-no-newline-single-line-elements": "error",
106
110
  "nextfriday/jsx-no-non-component-function": "error",
107
111
  "nextfriday/jsx-no-variable-in-callback": "error",
108
112
  "nextfriday/jsx-require-suspense": "error",
109
113
  "nextfriday/jsx-simple-props": "error",
114
+ "nextfriday/jsx-sort-props": "error",
110
115
  "nextfriday/prefer-jsx-template-literals": "error",
111
116
  "nextfriday/react-props-destructure": "error",
112
117
  "nextfriday/enforce-props-suffix": "error",
@@ -198,6 +203,8 @@ module.exports = {
198
203
  | [no-relative-imports](docs/rules/NO_RELATIVE_IMPORTS.md) | Disallow relative imports with ../ - use absolute imports | ❌ |
199
204
  | [prefer-import-type](docs/rules/PREFER_IMPORT_TYPE.md) | Enforce using 'import type' for type-only imports | ✅ |
200
205
  | [prefer-react-import-types](docs/rules/PREFER_REACT_IMPORT_TYPES.md) | Enforce direct imports from 'react' instead of React.X | ✅ |
206
+ | [sort-exports](docs/rules/SORT_EXPORTS.md) | Enforce a consistent ordering of export groups | ❌ |
207
+ | [sort-imports](docs/rules/SORT_IMPORTS.md) | Enforce a consistent ordering of import groups | ❌ |
201
208
 
202
209
  ### Type Pattern Rules
203
210
 
@@ -205,22 +212,25 @@ module.exports = {
205
212
  | -------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | ------- |
206
213
  | [prefer-named-param-types](docs/rules/PREFER_NAMED_PARAM_TYPES.md) | Enforce named types for function parameters with object types | ❌ |
207
214
  | [prefer-interface-over-inline-types](docs/rules/PREFER_INTERFACE_OVER_INLINE_TYPES.md) | Enforce interface declarations over inline types for React props | ❌ |
215
+ | [sort-type-alphabetically](docs/rules/SORT_TYPE_ALPHABETICALLY.md) | Enforce A-Z sorting of properties within type groups | ❌ |
208
216
  | [sort-type-required-first](docs/rules/SORT_TYPE_REQUIRED_FIRST.md) | Enforce required properties before optional in types/interfaces | ❌ |
209
217
 
210
218
  ### React/JSX Rules
211
219
 
212
- | Rule | Description | Fixable |
213
- | ---------------------------------------------------------------------------------- | --------------------------------------------------------------------- | ------- |
214
- | [jsx-newline-between-elements](docs/rules/JSX_NEWLINE_BETWEEN_ELEMENTS.md) | Require empty lines between sibling multi-line JSX elements | ✅ |
215
- | [jsx-no-inline-object-prop](docs/rules/JSX_NO_INLINE_OBJECT_PROP.md) | Disallow inline object literals in JSX props | ❌ |
216
- | [jsx-no-non-component-function](docs/rules/JSX_NO_NON_COMPONENT_FUNCTION.md) | Disallow non-component functions at top level in .tsx/.jsx files | |
217
- | [jsx-no-variable-in-callback](docs/rules/JSX_NO_VARIABLE_IN_CALLBACK.md) | Disallow variable declarations inside callback functions in JSX | ❌ |
218
- | [jsx-require-suspense](docs/rules/JSX_REQUIRE_SUSPENSE.md) | Require lazy-loaded components to be wrapped in Suspense | ❌ |
219
- | [jsx-simple-props](docs/rules/JSX_SIMPLE_PROPS.md) | Enforce simple prop values (strings, variables, callbacks, ReactNode) | ❌ |
220
- | [prefer-jsx-template-literals](docs/rules/PREFER_JSX_TEMPLATE_LITERALS.md) | Enforce template literals instead of mixing text and JSX expressions | |
221
- | [react-props-destructure](docs/rules/REACT_PROPS_DESTRUCTURE.md) | Enforce destructuring props inside React component body | ❌ |
222
- | [enforce-props-suffix](docs/rules/ENFORCE_PROPS_SUFFIX.md) | Enforce 'Props' suffix for interfaces and types in \*.tsx files | |
223
- | [enforce-readonly-component-props](docs/rules/ENFORCE_READONLY_COMPONENT_PROPS.md) | Enforce Readonly wrapper for React component props | |
220
+ | Rule | Description | Fixable |
221
+ | ---------------------------------------------------------------------------------------- | --------------------------------------------------------------------- | ------- |
222
+ | [jsx-newline-between-elements](docs/rules/JSX_NEWLINE_BETWEEN_ELEMENTS.md) | Require empty lines between sibling multi-line JSX elements | ✅ |
223
+ | [jsx-no-inline-object-prop](docs/rules/JSX_NO_INLINE_OBJECT_PROP.md) | Disallow inline object literals in JSX props | ❌ |
224
+ | [jsx-no-newline-single-line-elements](docs/rules/JSX_NO_NEWLINE_SINGLE_LINE_ELEMENTS.md) | Disallow empty lines between single-line sibling JSX elements | |
225
+ | [jsx-no-non-component-function](docs/rules/JSX_NO_NON_COMPONENT_FUNCTION.md) | Disallow non-component functions at top level in .tsx/.jsx files | ❌ |
226
+ | [jsx-no-variable-in-callback](docs/rules/JSX_NO_VARIABLE_IN_CALLBACK.md) | Disallow variable declarations inside callback functions in JSX | ❌ |
227
+ | [jsx-require-suspense](docs/rules/JSX_REQUIRE_SUSPENSE.md) | Require lazy-loaded components to be wrapped in Suspense | ❌ |
228
+ | [jsx-simple-props](docs/rules/JSX_SIMPLE_PROPS.md) | Enforce simple prop values (strings, variables, callbacks, ReactNode) | |
229
+ | [jsx-sort-props](docs/rules/JSX_SORT_PROPS.md) | Enforce JSX props are sorted by value type | ❌ |
230
+ | [prefer-jsx-template-literals](docs/rules/PREFER_JSX_TEMPLATE_LITERALS.md) | Enforce template literals instead of mixing text and JSX expressions | |
231
+ | [react-props-destructure](docs/rules/REACT_PROPS_DESTRUCTURE.md) | Enforce destructuring props inside React component body | |
232
+ | [enforce-props-suffix](docs/rules/ENFORCE_PROPS_SUFFIX.md) | Enforce 'Props' suffix for interfaces and types in \*.tsx files | ❌ |
233
+ | [enforce-readonly-component-props](docs/rules/ENFORCE_READONLY_COMPONENT_PROPS.md) | Enforce Readonly wrapper for React component props | ✅ |
224
234
 
225
235
  ### Next.js Rules
226
236
 
@@ -234,14 +244,14 @@ module.exports = {
234
244
 
235
245
  | Preset | Severity | Base Rules | JSX Rules | Next.js Rules | Total Rules |
236
246
  | -------------------- | -------- | ---------- | --------- | ------------- | ----------- |
237
- | `base` | warn | 30 | 0 | 0 | 30 |
238
- | `base/recommended` | error | 30 | 0 | 0 | 30 |
239
- | `react` | warn | 30 | 12 | 0 | 42 |
240
- | `react/recommended` | error | 30 | 12 | 0 | 42 |
241
- | `nextjs` | warn | 30 | 12 | 1 | 43 |
242
- | `nextjs/recommended` | error | 30 | 12 | 1 | 43 |
247
+ | `base` | warn | 33 | 0 | 0 | 33 |
248
+ | `base/recommended` | error | 33 | 0 | 0 | 33 |
249
+ | `react` | warn | 33 | 14 | 0 | 47 |
250
+ | `react/recommended` | error | 33 | 14 | 0 | 47 |
251
+ | `nextjs` | warn | 33 | 14 | 1 | 48 |
252
+ | `nextjs/recommended` | error | 33 | 14 | 1 | 48 |
243
253
 
244
- ### Base Configuration Rules (30 rules)
254
+ ### Base Configuration Rules (33 rules)
245
255
 
246
256
  Included in `base`, `base/recommended`, and all other presets:
247
257
 
@@ -274,9 +284,12 @@ Included in `base`, `base/recommended`, and all other presets:
274
284
  - `nextfriday/prefer-named-param-types`
275
285
  - `nextfriday/prefer-react-import-types`
276
286
  - `nextfriday/require-explicit-return-type`
287
+ - `nextfriday/sort-exports`
288
+ - `nextfriday/sort-imports`
289
+ - `nextfriday/sort-type-alphabetically`
277
290
  - `nextfriday/sort-type-required-first`
278
291
 
279
- ### JSX Rules (12 rules)
292
+ ### JSX Rules (14 rules)
280
293
 
281
294
  Additionally included in `react`, `react/recommended`, `nextjs`, `nextjs/recommended`:
282
295
 
@@ -284,11 +297,13 @@ Additionally included in `react`, `react/recommended`, `nextjs`, `nextjs/recomme
284
297
  - `nextfriday/enforce-readonly-component-props`
285
298
  - `nextfriday/jsx-newline-between-elements`
286
299
  - `nextfriday/jsx-no-inline-object-prop`
300
+ - `nextfriday/jsx-no-newline-single-line-elements`
287
301
  - `nextfriday/jsx-no-non-component-function`
288
302
  - `nextfriday/jsx-no-variable-in-callback`
289
303
  - `nextfriday/jsx-pascal-case`
290
304
  - `nextfriday/jsx-require-suspense`
291
305
  - `nextfriday/jsx-simple-props`
306
+ - `nextfriday/jsx-sort-props`
292
307
  - `nextfriday/prefer-interface-over-inline-types`
293
308
  - `nextfriday/prefer-jsx-template-literals`
294
309
  - `nextfriday/react-props-destructure`
@@ -0,0 +1,76 @@
1
+ # jsx-no-newline-single-line-elements
2
+
3
+ Disallow empty lines between single-line sibling JSX elements.
4
+
5
+ ## Rule Details
6
+
7
+ This rule enforces that sibling JSX elements which are both single-line should not have empty lines between them. Single-line elements should be compact and grouped together.
8
+
9
+ Use with `jsx-newline-between-elements` which requires empty lines between multi-line siblings.
10
+
11
+ ### Why?
12
+
13
+ 1. **Readability**: Single-line elements that are visually similar should be grouped together without gaps
14
+ 2. **Consistency**: Prevents inconsistent spacing between elements of the same visual weight
15
+ 3. **Complementary**: Works alongside `jsx-newline-between-elements` to create clear visual separation only where it matters
16
+
17
+ ## Examples
18
+
19
+ ### ❌ Incorrect
20
+
21
+ ```tsx
22
+ // Bad: Unnecessary empty line between single-line siblings
23
+ <div>
24
+ <Panel id="courses">Courses</Panel>
25
+
26
+ <Panel id="news">News</Panel>
27
+ </div>
28
+ ```
29
+
30
+ ```tsx
31
+ // Bad: Empty lines between single-line list items
32
+ <ul>
33
+ <li>Item 1</li>
34
+
35
+ <li>Item 2</li>
36
+
37
+ <li>Item 3</li>
38
+ </ul>
39
+ ```
40
+
41
+ ### ✅ Correct
42
+
43
+ ```tsx
44
+ // Good: Single-line siblings are compact
45
+ <div>
46
+ <Panel id="courses">Courses</Panel>
47
+ <Panel id="news">News</Panel>
48
+ </div>
49
+ ```
50
+
51
+ ```tsx
52
+ // Good: Multi-line sibling has empty line (handled by jsx-newline-between-elements)
53
+ <div>
54
+ <Panel id="overview">
55
+ <div className="grid gap-8">
56
+ <div>Content</div>
57
+ </div>
58
+ </Panel>
59
+
60
+ <Panel id="courses">Courses</Panel>
61
+ <Panel id="news">News</Panel>
62
+ </div>
63
+ ```
64
+
65
+ ```tsx
66
+ // Good: Self-closing components without empty lines
67
+ <div>
68
+ <Header />
69
+ <Main />
70
+ <Footer />
71
+ </div>
72
+ ```
73
+
74
+ ## When Not To Use It
75
+
76
+ If you prefer empty lines between all sibling JSX elements regardless of their line count, you can disable this rule.
@@ -0,0 +1,58 @@
1
+ # jsx-sort-props
2
+
3
+ Enforce JSX props are sorted by value type.
4
+
5
+ ## Rule Details
6
+
7
+ This rule enforces a consistent ordering of JSX props based on the type of their value. Props must appear in the following order:
8
+
9
+ 1. **String** - String literals and template literals
10
+ 2. **Number/Boolean/Null** - Numeric literals, boolean literals, null, and undefined
11
+ 3. **Object/Array** - Inline objects and arrays
12
+ 4. **Function** - Arrow functions and function expressions
13
+ 5. **JSX Element** - JSX elements and fragments
14
+ 6. **Shorthand boolean** - Props with no value (e.g., `disabled`)
15
+
16
+ Props with values that cannot be statically determined (variables, member expressions, call expressions, etc.) are skipped and do not affect the ordering check. Spread attributes (`{...props}`) reset the ordering context.
17
+
18
+ ### Why?
19
+
20
+ - **Readability**: Grouping props by type makes components easier to scan
21
+ - **Consistency**: Enforces a uniform prop ordering convention across the codebase
22
+ - **Predictability**: Developers know where to find specific prop types at a glance
23
+
24
+ ## Examples
25
+
26
+ ### ❌ Incorrect
27
+
28
+ ```tsx
29
+ <Component disabled title="hello" />
30
+ <Component onClick={() => {}} count={42} />
31
+ <Component icon={<Icon />} style={{ color: "red" }} />
32
+ ```
33
+
34
+ ### ✅ Correct
35
+
36
+ ```tsx
37
+ <Component
38
+ title="hello"
39
+ count={100}
40
+ style={{ color: "red" }}
41
+ onClick={() => handleClick()}
42
+ icon={<HomeIcon />}
43
+ disabled
44
+ />
45
+
46
+ <Component title="hello" count={42} disabled />
47
+
48
+ <Component value={someVar} disabled />
49
+ ```
50
+
51
+ ## When Not To Use It
52
+
53
+ - If your team prefers alphabetical or custom prop ordering
54
+ - If you use a different prop sorting convention
55
+
56
+ ## Related Rules
57
+
58
+ - [jsx-simple-props](./JSX_SIMPLE_PROPS.md) - Enforce simple prop values
@@ -0,0 +1,68 @@
1
+ # sort-exports
2
+
3
+ Enforce a consistent ordering of export groups.
4
+
5
+ ## Rule Details
6
+
7
+ This rule enforces that named export statements (without declarations) are grouped and ordered by their source type. It does not enforce alphabetical sorting within groups.
8
+
9
+ ### Why?
10
+
11
+ 1. **Readability**: Grouping exports by source type makes barrel files and re-export modules easier to scan
12
+ 2. **Consistency**: A predictable export order reduces merge conflicts and code review friction
13
+ 3. **Separation of concerns**: Re-exports from external/internal sources vs local exports serve different purposes
14
+
15
+ ### Export Group Order
16
+
17
+ 1. **External/alias re-exports** — source matches a package name or alias (`@/`, `~/`, `#`) (e.g., `export { foo } from "react"`)
18
+ 2. **Relative re-exports** — source starts with `.` (e.g., `export { bar } from "../bar"`)
19
+ 3. **Local exports** — no source (e.g., `export { baz }`)
20
+
21
+ Skipped (breaks contiguity): `export default`, `export *`, `export const/function/class` (declarations).
22
+
23
+ Non-contiguous exports (separated by other statements) are checked independently.
24
+
25
+ ## Examples
26
+
27
+ ### ❌ Incorrect
28
+
29
+ ```ts
30
+ // Bad: Local before re-export
31
+ export { bar };
32
+ export { foo } from "react";
33
+ ```
34
+
35
+ ```ts
36
+ // Bad: Relative before external
37
+ export { bar } from "../bar";
38
+ export { foo } from "react";
39
+ ```
40
+
41
+ ### ✅ Correct
42
+
43
+ ```ts
44
+ // Good: All 3 groups in correct order
45
+ export { foo } from "@/lib/foo";
46
+ export { bar } from "../bar";
47
+ export { baz };
48
+ ```
49
+
50
+ ```ts
51
+ // Good: Non-contiguous exports are independent
52
+ export { foo } from "react";
53
+
54
+ const x = 1;
55
+
56
+ export { bar };
57
+ ```
58
+
59
+ ```ts
60
+ // Good: Export declarations break contiguity
61
+ export const x = 1;
62
+ export { foo } from "./foo";
63
+ export { bar };
64
+ ```
65
+
66
+ ## When Not To Use It
67
+
68
+ If you prefer a different export ordering convention or don't want to enforce any particular order for exports, you can disable this rule.
@@ -0,0 +1,78 @@
1
+ # sort-imports
2
+
3
+ Enforce a consistent ordering of import groups.
4
+
5
+ ## Rule Details
6
+
7
+ This rule enforces that import statements are grouped and ordered by their source type. It does not enforce alphabetical sorting within groups.
8
+
9
+ ### Why?
10
+
11
+ 1. **Readability**: Grouping imports by source type makes it easy to scan dependencies at a glance
12
+ 2. **Consistency**: A predictable import order reduces merge conflicts and code review friction
13
+ 3. **Separation of concerns**: Side effects, platform modules, third-party packages, internal aliases, and relative imports serve different purposes
14
+
15
+ ### Import Group Order
16
+
17
+ 1. **Side-effect imports** — no specifiers (e.g., `import "./setup"`)
18
+ 2. **Node.js builtins** — `node:` prefix or known builtin names (e.g., `import fs from "node:fs"`)
19
+ 3. **External packages** — scoped or plain package names (e.g., `import React from "react"`)
20
+ 4. **Internal aliases** — paths starting with `@/`, `~/`, or `#` (e.g., `import { utils } from "@/lib/utils"`)
21
+ 5. **Relative imports** — paths starting with `.` (e.g., `import { foo } from "../foo"`)
22
+
23
+ Type-only imports (`import type`) are skipped and do not affect ordering.
24
+
25
+ Non-contiguous imports (separated by other statements) are checked independently.
26
+
27
+ ## Examples
28
+
29
+ ### ❌ Incorrect
30
+
31
+ ```ts
32
+ // Bad: Relative before external
33
+ import { foo } from "../foo";
34
+ import React from "react";
35
+ ```
36
+
37
+ ```ts
38
+ // Bad: External before builtin
39
+ import React from "react";
40
+ import fs from "node:fs";
41
+ ```
42
+
43
+ ```ts
44
+ // Bad: Side-effect after external
45
+ import React from "react";
46
+ import "./setup";
47
+ ```
48
+
49
+ ### ✅ Correct
50
+
51
+ ```ts
52
+ // Good: All 5 groups in correct order
53
+ import "./setup";
54
+ import fs from "node:fs";
55
+ import React from "react";
56
+ import { utils } from "@/lib/utils";
57
+ import { foo } from "../foo";
58
+ ```
59
+
60
+ ```ts
61
+ // Good: Type imports can appear anywhere
62
+ import type { FC } from "react";
63
+ import { foo } from "../foo";
64
+ import React from "react";
65
+ ```
66
+
67
+ ```ts
68
+ // Good: Non-contiguous imports are independent
69
+ import React from "react";
70
+
71
+ const x = 1;
72
+
73
+ import { foo } from "../foo";
74
+ ```
75
+
76
+ ## When Not To Use It
77
+
78
+ If you use a different import sorting tool (e.g., `eslint-plugin-simple-import-sort`) or prefer a different group ordering, you can disable this rule.
@@ -0,0 +1,104 @@
1
+ # sort-type-alphabetically
2
+
3
+ Enforce alphabetical sorting of properties within required and optional groups in TypeScript interfaces and type aliases.
4
+
5
+ ## Rule Details
6
+
7
+ This rule enforces that TypeScript interface and type alias properties are sorted alphabetically (A-Z) within their respective groups (required and optional). It checks each group independently.
8
+
9
+ ### Why?
10
+
11
+ 1. **Readability**: Alphabetical ordering makes properties easier to find
12
+ 2. **Consistency**: A predictable ordering reduces cognitive load during code review
13
+ 3. **Maintainability**: Clear structure makes it easier to add or remove properties
14
+
15
+ ### Sorting Order
16
+
17
+ Properties within each group are sorted alphabetically A-Z:
18
+
19
+ 1. **Required properties** sorted A-Z among themselves
20
+ 2. **Optional properties** sorted A-Z among themselves
21
+
22
+ Use with `sort-type-required-first` to also enforce required properties come before optional.
23
+
24
+ ## Examples
25
+
26
+ ### ❌ Incorrect
27
+
28
+ ```ts
29
+ // Bad: Required not sorted A-Z
30
+ interface Props {
31
+ src: string;
32
+ alt: string;
33
+ }
34
+ ```
35
+
36
+ ```ts
37
+ // Bad: Optional not sorted A-Z
38
+ interface Props {
39
+ b?: number;
40
+ a?: string;
41
+ }
42
+ ```
43
+
44
+ ```ts
45
+ // Bad: Required group not sorted A-Z
46
+ interface HeroBannerRootProps {
47
+ size: "detail" | "highlight" | "main";
48
+ alt: string;
49
+ src: string;
50
+ className?: string;
51
+ label?: string;
52
+ }
53
+ ```
54
+
55
+ ### ✅ Correct
56
+
57
+ ```ts
58
+ // Good: Required A-Z, optional A-Z
59
+ interface HeroBannerRootProps {
60
+ alt: string;
61
+ size: "detail" | "highlight" | "main";
62
+ src: string;
63
+ className?: string;
64
+ label?: string;
65
+ onClick?: () => void;
66
+ }
67
+ ```
68
+
69
+ ```ts
70
+ // Good: All required, sorted A-Z
71
+ interface Props {
72
+ a: string;
73
+ b: number;
74
+ c: boolean;
75
+ }
76
+ ```
77
+
78
+ ```ts
79
+ // Good: All optional, sorted A-Z
80
+ interface Props {
81
+ a?: string;
82
+ b?: number;
83
+ c?: boolean;
84
+ }
85
+ ```
86
+
87
+ ```ts
88
+ // Good: Type alias with A-Z within groups
89
+ type Props = {
90
+ alt: string;
91
+ size: string;
92
+ src: string;
93
+ label?: string;
94
+ };
95
+ ```
96
+
97
+ ## When Not To Use It
98
+
99
+ If you prefer a different sorting strategy for type properties or don't want to enforce alphabetical ordering, you can disable this rule.
100
+
101
+ ## Further Reading
102
+
103
+ - [TypeScript Interfaces](https://www.typescriptlang.org/docs/handbook/2/objects.html)
104
+ - [TypeScript Type Aliases](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-aliases)
@@ -1,24 +1,23 @@
1
1
  # sort-type-required-first
2
2
 
3
- Enforce required properties come before optional properties in TypeScript interfaces and type aliases, with alphabetical sorting within each group.
3
+ Enforce required properties come before optional properties in TypeScript interfaces and type aliases.
4
4
 
5
5
  ## Rule Details
6
6
 
7
- This rule enforces that TypeScript interface and type alias properties are sorted with required (non-optional) properties first, then optional properties. Both groups are sorted alphabetically (A-Z).
7
+ This rule enforces that TypeScript interface and type alias required (non-optional) properties come before optional properties.
8
8
 
9
9
  ### Why?
10
10
 
11
- 1. **Consistency**: A predictable ordering makes code easier to scan and review
12
- 2. **Readability**: Required properties are the most important contract of a type - they should be visible first
13
- 3. **Organization**: Grouping by optionality clearly communicates which properties are mandatory
14
- 4. **Maintainability**: Clear structure makes it easier to add or remove properties
11
+ 1. **Readability**: Required properties are the most important contract of a type - they should be visible first
12
+ 2. **Organization**: Grouping by optionality clearly communicates which properties are mandatory
13
+ 3. **Consistency**: A predictable ordering makes code easier to scan and review
15
14
 
16
15
  ### Sorting Order
17
16
 
18
- Properties are sorted in this order:
17
+ 1. **Required properties** first
18
+ 2. **Optional properties** after
19
19
 
20
- 1. **Required properties** (sorted alphabetically A-Z)
21
- 2. **Optional properties** (sorted alphabetically A-Z)
20
+ Use with `sort-type-alphabetically` to also enforce A-Z ordering within each group.
22
21
 
23
22
  ## Examples
24
23
 
@@ -44,35 +43,19 @@ interface Props {
44
43
  ```
45
44
 
46
45
  ```ts
47
- // Bad: Required not sorted alphabetically
46
+ // Bad: Required after optional
48
47
  interface Props {
49
- src: string;
50
- alt: string;
51
- }
52
- ```
53
-
54
- ```ts
55
- // Bad: Optional not sorted alphabetically
56
- interface Props {
57
- b?: number;
58
- a?: string;
48
+ a: string;
49
+ b: string;
50
+ c?: string;
51
+ d: string;
59
52
  }
60
53
  ```
61
54
 
62
- ```ts
63
- // Bad: Type alias with optional before required
64
- type Props = {
65
- label?: string;
66
- alt: string;
67
- size: string;
68
- src: string;
69
- };
70
- ```
71
-
72
55
  ### ✅ Correct
73
56
 
74
57
  ```ts
75
- // Good: Required first alphabetically, then optional
58
+ // Good: Required first, then optional
76
59
  interface HeroBannerRootProps {
77
60
  alt: string;
78
61
  size: "detail" | "highlight" | "main";
@@ -82,7 +65,7 @@ interface HeroBannerRootProps {
82
65
  ```
83
66
 
84
67
  ```ts
85
- // Good: All required, sorted alphabetically
68
+ // Good: All required
86
69
  interface Props {
87
70
  a: string;
88
71
  b: number;
@@ -91,7 +74,7 @@ interface Props {
91
74
  ```
92
75
 
93
76
  ```ts
94
- // Good: All optional, sorted alphabetically
77
+ // Good: All optional
95
78
  interface Props {
96
79
  a?: string;
97
80
  b?: number;
@@ -100,7 +83,7 @@ interface Props {
100
83
  ```
101
84
 
102
85
  ```ts
103
- // Good: Type alias with required first then optional
86
+ // Good: Type alias with required first
104
87
  type Props = {
105
88
  alt: string;
106
89
  size: string;
@@ -109,20 +92,9 @@ type Props = {
109
92
  };
110
93
  ```
111
94
 
112
- ```ts
113
- // Good: Multiple optional at end, sorted alphabetically
114
- interface Props {
115
- alt: string;
116
- size: "detail" | "highlight" | "main";
117
- src: string;
118
- label?: string;
119
- visible?: boolean;
120
- }
121
- ```
122
-
123
95
  ## When Not To Use It
124
96
 
125
- If you prefer a different sorting strategy for type properties or don't want to enforce any particular order, you can disable this rule.
97
+ If you prefer a different grouping strategy for type properties or don't want to enforce any particular order, you can disable this rule.
126
98
 
127
99
  ## Further Reading
128
100