Repository: azat-io/eslint-plugin-perfectionist
Pull request #474 (2025-02-19 13:00:43)

feat: add `customGroups.fallbackSort` option
Follow-up of https://github.com/azat-io/eslint-plugin-perfectionist/pull/457 and https://github.com/azat-io/eslint-plugin-perfectionist/pull/469.

### Description

This PR does the following: 

- Adds a `customGroups.fallbackSort` option to rules that support the array-based `customGroups` API.
- Adds the `fallbackSort` option to `settings`.
- Improves documentation readability.
- Refactors `compare`, `sort-nodes` and `sort-nodes-by-groups` in order to prepare for the next PR that will allow us to finally let `sort-object-types` and `sort-interfaces` handle `customGroups.fallbackSort.sortBy`.
- Adds missing tests.

### What is the purpose of this pull request?

- [x] New Feature



Patch:
diff --git a/docs/components/Community/CommunityBlock.astro b/docs/components/Community/CommunityBlock.astro
index f6edcd1..92e06a1 100644
--- a/docs/components/Community/CommunityBlock.astro
+++ b/docs/components/Community/CommunityBlock.astro
@@ -18,7 +18,7 @@ if (!releases) {
 }
 
 let stars = '2.3k'
-let downloads = '2M'
+let downloads = '2.2M'
 ---
 
 <section class="section">
diff --git a/docs/content/guide/getting-started.mdx b/docs/content/guide/getting-started.mdx
index d6a3522..4db16c7 100644
--- a/docs/content/guide/getting-started.mdx
+++ b/docs/content/guide/getting-started.mdx
@@ -142,6 +142,7 @@ In settings you can set the following options:
 
 - `type` — The type of sorting. Possible values are `'alphabetical'`, `'natural'`, `'line-length'` and `custom`.
 - `order` — The order of sorting. Possible values are `'asc'` and `'desc'`.
+- `fallbackSort` — The fallback sorting type and order to use when two elements are equal.
 - `alphabet` — The custom alphabet to use when `type` is `custom`.
 - `ignoreCase` — Ignore case when sorting.
 - `ignorePattern` — Ignore sorting for elements that match the pattern.
diff --git a/docs/content/rules/sort-array-includes.mdx b/docs/content/rules/sort-array-includes.mdx
index 8c33840..ec337d8 100644
--- a/docs/content/rules/sort-array-includes.mdx
+++ b/docs/content/rules/sort-array-includes.mdx
@@ -143,7 +143,13 @@ Determines whether the sorted items should be in ascending or descending order.
 ### fallbackSort
 
 <sub>
-  type: `{ type: string; order?: 'asc' | 'desc' }`
+  type:
+  ```
+  {
+    type: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
+    order?: 'asc' | 'desc'
+  }
+  ```
 </sub>
 <sub>default: `{ type: 'unsorted' }`</sub>
 
@@ -371,6 +377,7 @@ interface CustomGroupDefinition {
   groupName: string
   type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
   order?: 'asc' | 'desc'
+  fallbackSort?: { type: string; order?: 'asc' | 'desc' }
   selector?: string
   elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
 }
@@ -385,6 +392,7 @@ interface CustomGroupAnyOfDefinition {
   groupName: string
   type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
   order?: 'asc' | 'desc'
+  fallbackSort?: { type: string; order?: 'asc' | 'desc' }
   anyOf: Array<{
       selector?: string
       elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
@@ -401,6 +409,7 @@ An array element will match a `CustomGroupAnyOfDefinition` group if it matches a
 - `elementNamePattern`: If entered, will check that the name of the element matches the pattern entered.
 - `type`: Overrides the sort type for that custom group. `unsorted` will not sort the group.
 - `order`: Overrides the sort order for that custom group
+- `fallbackSort`: Overrides the fallbackSort option for that custom group
 
 #### Match importance
 
diff --git a/docs/content/rules/sort-classes.mdx b/docs/content/rules/sort-classes.mdx
index 6721685..d9a6785 100644
--- a/docs/content/rules/sort-classes.mdx
+++ b/docs/content/rules/sort-classes.mdx
@@ -178,7 +178,13 @@ Determines whether the sorted items should be in ascending or descending order.
 ### fallbackSort
 
 <sub>
-  type: `{ type: string; order?: 'asc' | 'desc' }`
+  type:
+  ```
+  {
+    type: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
+    order?: 'asc' | 'desc'
+  }
+  ```
 </sub>
 <sub>default: `{ type: 'unsorted' }`</sub>
 
@@ -647,6 +653,7 @@ interface CustomGroupDefinition {
   groupName: string
   type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
   order?: 'asc' | 'desc'
+  fallbackSort?: { type: string; order?: 'asc' | 'desc' }
   newlinesInside?: 'always' | 'never'
   selector?: string
   modifiers?: string[]
@@ -664,6 +671,7 @@ interface CustomGroupAnyOfDefinition {
   groupName: string
   type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
   order?: 'asc' | 'desc'
+  fallbackSort?: { type: string; order?: 'asc' | 'desc' }
   newlinesInside?: 'always' | 'never'
   anyOf: Array<{
       selector?: string
@@ -687,6 +695,7 @@ A class member will match a `CustomGroupAnyOfDefinition` group if it matches all
 - `decoratorNamePattern`: If entered, will check that at least one `decorator` matches the pattern entered.
 - `type`: Overrides the sort type for that custom group. `unsorted` will not sort the group.
 - `order`: Overrides the sort order for that custom group
+- `fallbackSort`: Overrides the fallbackSort option for that custom group
 - `newlinesInside`: Enforces a specific newline behavior between elements of the group.
 
 #### Match importance
diff --git a/docs/content/rules/sort-decorators.mdx b/docs/content/rules/sort-decorators.mdx
index 91be888..e8230d7 100644
--- a/docs/content/rules/sort-decorators.mdx
+++ b/docs/content/rules/sort-decorators.mdx
@@ -142,7 +142,13 @@ Determines whether the sorted items should be in ascending or descending order.
 ### fallbackSort
 
 <sub>
-  type: `{ type: string; order?: 'asc' | 'desc' }`
+  type:
+  ```
+  {
+    type: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
+    order?: 'asc' | 'desc'
+  }
+  ```
 </sub>
 <sub>default: `{ type: 'unsorted' }`</sub>
 
diff --git a/docs/content/rules/sort-enums.mdx b/docs/content/rules/sort-enums.mdx
index 27b6ea4..60439da 100644
--- a/docs/content/rules/sort-enums.mdx
+++ b/docs/content/rules/sort-enums.mdx
@@ -108,7 +108,13 @@ Determines whether the sorted items should be in ascending or descending order.
 ### fallbackSort
 
 <sub>
-  type: `{ type: string; order?: 'asc' | 'desc' }`
+  type:
+  ```
+  {
+    type: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
+    order?: 'asc' | 'desc'
+  }
+  ```
 </sub>
 <sub>default: `{ type: 'unsorted' }`</sub>
 
@@ -285,6 +291,7 @@ interface CustomGroupDefinition {
   groupName: string
   type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
   order?: 'asc' | 'desc'
+  fallbackSort?: { type: string; order?: 'asc' | 'desc' }
   elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
 }
 
@@ -298,6 +305,7 @@ interface CustomGroupAnyOfDefinition {
   groupName: string
   type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
   order?: 'asc' | 'desc'
+  fallbackSort?: { type: string; order?: 'asc' | 'desc' }
   anyOf: Array<{
       elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
   }>
@@ -313,6 +321,7 @@ An enum member will match a `CustomGroupAnyOfDefinition` group if it matches all
 - `elementValuePattern`: If entered, will check that the value of the element matches the pattern entered.
 - `type`: Overrides the sort type for that custom group. `unsorted` will not sort the group.
 - `order`: Overrides the sort order for that custom group
+- `fallbackSort`: Overrides the fallbackSort option for that custom group
 
 #### Match importance
 
diff --git a/docs/content/rules/sort-exports.mdx b/docs/content/rules/sort-exports.mdx
index d027cfe..1dc19bd 100644
--- a/docs/content/rules/sort-exports.mdx
+++ b/docs/content/rules/sort-exports.mdx
@@ -102,7 +102,13 @@ Determines whether the sorted items should be in ascending or descending order.
 ### fallbackSort
 
 <sub>
-  type: `{ type: string; order?: 'asc' | 'desc' }`
+  type:
+  ```
+  {
+    type: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
+    order?: 'asc' | 'desc'
+  }
+  ```
 </sub>
 <sub>default: `{ type: 'unsorted' }`</sub>
 
diff --git a/docs/content/rules/sort-heritage-clauses.mdx b/docs/content/rules/sort-heritage-clauses.mdx
index 2f7278c..9d17cce 100644
--- a/docs/content/rules/sort-heritage-clauses.mdx
+++ b/docs/content/rules/sort-heritage-clauses.mdx
@@ -85,7 +85,13 @@ Determines whether the sorted items should be in ascending or descending order.
 ### fallbackSort
 
 <sub>
-  type: `{ type: string; order?: 'asc' | 'desc' }`
+  type:
+  ```
+  {
+    type: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
+    order?: 'asc' | 'desc'
+  }
+  ```
 </sub>
 <sub>default: `{ type: 'unsorted' }`</sub>
 
diff --git a/docs/content/rules/sort-imports.mdx b/docs/content/rules/sort-imports.mdx
index d552600..d30f986 100644
--- a/docs/content/rules/sort-imports.mdx
+++ b/docs/content/rules/sort-imports.mdx
@@ -141,7 +141,13 @@ Determines whether the sorted items should be in ascending or descending order.
 ### fallbackSort
 
 <sub>
-  type: `{ type: string; order?: 'asc' | 'desc' }`
+  type:
+  ```
+  {
+    type: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
+    order?: 'asc' | 'desc'
+  }
+  ```
 </sub>
 <sub>default: `{ type: 'unsorted' }`</sub>
 
diff --git a/docs/content/rules/sort-interfaces.mdx b/docs/content/rules/sort-interfaces.mdx
index 0827740..3532e72 100644
--- a/docs/content/rules/sort-interfaces.mdx
+++ b/docs/content/rules/sort-interfaces.mdx
@@ -157,7 +157,13 @@ Determines whether the sorted items should be in ascending or descending order.
 ### fallbackSort
 
 <sub>
-  type: `{ type: string; order?: 'asc' | 'desc' }`
+  type:
+  ```
+  {
+    type: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
+    order?: 'asc' | 'desc'
+  }
+  ```
 </sub>
 <sub>default: `{ type: 'unsorted' }`</sub>
 
@@ -554,6 +560,7 @@ interface CustomGroupDefinition {
   groupName: string
   type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
   order?: 'asc' | 'desc'
+  fallbackSort?: { type: string; order?: 'asc' | 'desc' }
   sortBy?: 'name' | 'value'
   newlinesInside?: 'always' | 'never'
   selector?: string
@@ -572,6 +579,7 @@ interface CustomGroupAnyOfDefinition {
   groupName: string
   type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
   order?: 'asc' | 'desc'
+  fallbackSort?: { type: string; order?: 'asc' | 'desc' }
   sortBy?: 'name' | 'value'
   newlinesInside?: 'always' | 'never'
   anyOf: Array<{
@@ -594,6 +602,7 @@ An interface member will match a `CustomGroupAnyOfDefinition` group if it matche
 - `elementValuePattern`: Only for properties. If entered, will check that the value of the property matches the pattern entered.
 - `type`: Overrides the sort type for that custom group. `unsorted` will not sort the group.
 - `order`: Overrides the sort order for that custom group
+- `fallbackSort`: Overrides the fallbackSort option for that custom group
 - `sortBy`: Overrides the `sortBy` option for that custom group
 - `newlinesInside`: Enforces a specific newline behavior between elements of the group.
 
diff --git a/docs/content/rules/sort-intersection-types.mdx b/docs/content/rules/sort-intersection-types.mdx
index 0c3b21b..d804f81 100644
--- a/docs/content/rules/sort-intersection-types.mdx
+++ b/docs/content/rules/sort-intersection-types.mdx
@@ -98,7 +98,13 @@ Determines whether the sorted items should be in ascending or descending order.
 ### fallbackSort
 
 <sub>
-  type: `{ type: string; order?: 'asc' | 'desc' }`
+  type:
+  ```
+  {
+    type: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
+    order?: 'asc' | 'desc'
+  }
+  ```
 </sub>
 <sub>default: `{ type: 'unsorted' }`</sub>
 
diff --git a/docs/content/rules/sort-jsx-props.mdx b/docs/content/rules/sort-jsx-props.mdx
index 5764835..d88b13e 100644
--- a/docs/content/rules/sort-jsx-props.mdx
+++ b/docs/content/rules/sort-jsx-props.mdx
@@ -158,7 +158,13 @@ Determines whether the sorted items should be in ascending or descending order.
 ### fallbackSort
 
 <sub>
-  type: `{ type: string; order?: 'asc' | 'desc' }`
+  type:
+  ```
+  {
+    type: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
+    order?: 'asc' | 'desc'
+  }
+  ```
 </sub>
 <sub>default: `{ type: 'unsorted' }`</sub>
 
diff --git a/docs/content/rules/sort-maps.mdx b/docs/content/rules/sort-maps.mdx
index bd20657..fe5195f 100644
--- a/docs/content/rules/sort-maps.mdx
+++ b/docs/content/rules/sort-maps.mdx
@@ -103,7 +103,13 @@ Determines whether the sorted items should be in ascending or descending order.
 ### fallbackSort
 
 <sub>
-  type: `{ type: string; order?: 'asc' | 'desc' }`
+  type:
+  ```
+  {
+    type: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
+    order?: 'asc' | 'desc'
+  }
+  ```
 </sub>
 <sub>default: `{ type: 'unsorted' }`</sub>
 
@@ -315,6 +321,7 @@ interface CustomGroupDefinition {
   groupName: string
   type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
   order?: 'asc' | 'desc'
+  fallbackSort?: { type: string; order?: 'asc' | 'desc' }
   elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
 }
 
@@ -328,6 +335,7 @@ interface CustomGroupAnyOfDefinition {
   groupName: string
   type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
   order?: 'asc' | 'desc'
+  fallbackSort?: { type: string; order?: 'asc' | 'desc' }
   anyOf: Array<{
       elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
   }>
@@ -342,6 +350,7 @@ A map element will match a `CustomGroupAnyOfDefinition` group if it matches all
 - `elementNamePattern`: If entered, will check that the name of the element matches the pattern entered.
 - `type`: Overrides the sort type for that custom group. `unsorted` will not sort the group.
 - `order`: Overrides the sort order for that custom group
+- `fallbackSort`: Overrides the fallbackSort option for that custom group
 
 #### Match importance
 
diff --git a/docs/content/rules/sort-modules.mdx b/docs/content/rules/sort-modules.mdx
index e3b1004..0db6a9d 100644
--- a/docs/content/rules/sort-modules.mdx
+++ b/docs/content/rules/sort-modules.mdx
@@ -201,7 +201,13 @@ Determines whether the sorted items should be in ascending or descending order.
 ### fallbackSort
 
 <sub>
-  type: `{ type: string; order?: 'asc' | 'desc' }`
+  type:
+  ```
+  {
+    type: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
+    order?: 'asc' | 'desc'
+  }
+  ```
 </sub>
 <sub>default: `{ type: 'unsorted' }`</sub>
 
@@ -426,6 +432,7 @@ interface CustomGroupDefinition {
   groupName: string
   type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
   order?: 'asc' | 'desc'
+  fallbackSort?: { type: string; order?: 'asc' | 'desc' }
   newlinesInside?: 'always' | 'never'
   selector?: string
   modifiers?: string[]
@@ -442,6 +449,7 @@ interface CustomGroupAnyOfDefinition {
   groupName: string
   type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
   order?: 'asc' | 'desc'
+  fallbackSort?: { type: string; order?: 'asc' | 'desc' }
   newlinesInside?: 'always' | 'never'
   anyOf: Array<{
       selector?: string
@@ -463,6 +471,7 @@ A module member will match a `CustomGroupAnyOfDefinition` group if it matches al
 - `decoratorNamePattern`: If entered, will check that at least one `decorator` matches the pattern entered.
 - `type`: Overrides the sort type for that custom group. `unsorted` will not sort the group.
 - `order`: Overrides the sort order for that custom group
+- `fallbackSort`: Overrides the fallbackSort option for that custom group
 - `newlinesInside`: Enforces a specific newline behavior between elements of the group.
 
 #### Match importance
diff --git a/docs/content/rules/sort-named-exports.mdx b/docs/content/rules/sort-named-exports.mdx
index 8edb805..6ffc6e9 100644
--- a/docs/content/rules/sort-named-exports.mdx
+++ b/docs/content/rules/sort-named-exports.mdx
@@ -121,7 +121,13 @@ Determines whether the sorted items should be in ascending or descending order.
 ### fallbackSort
 
 <sub>
-  type: `{ type: string; order?: 'asc' | 'desc' }`
+  type:
+  ```
+  {
+    type: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
+    order?: 'asc' | 'desc'
+  }
+  ```
 </sub>
 <sub>default: `{ type: 'unsorted' }`</sub>
 
diff --git a/docs/content/rules/sort-named-imports.mdx b/docs/content/rules/sort-named-imports.mdx
index 1bc2231..51ee7df 100644
--- a/docs/content/rules/sort-named-imports.mdx
+++ b/docs/content/rules/sort-named-imports.mdx
@@ -122,7 +122,13 @@ Determines whether the sorted items should be in ascending or descending order.
 ### fallbackSort
 
 <sub>
-  type: `{ type: string; order?: 'asc' | 'desc' }`
+  type:
+  ```
+  {
+    type: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
+    order?: 'asc' | 'desc'
+  }
+  ```
 </sub>
 <sub>default: `{ type: 'unsorted' }`</sub>
 
diff --git a/docs/content/rules/sort-object-types.mdx b/docs/content/rules/sort-object-types.mdx
index b6dde35..2bf2926 100644
--- a/docs/content/rules/sort-object-types.mdx
+++ b/docs/content/rules/sort-object-types.mdx
@@ -119,7 +119,13 @@ Determines whether the sorted items should be in ascending or descending order.
 ### fallbackSort
 
 <sub>
-  type: `{ type: string; order?: 'asc' | 'desc' }`
+  type:
+  ```
+  {
+    type: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
+    order?: 'asc' | 'desc'
+  }
+  ```
 </sub>
 <sub>default: `{ type: 'unsorted' }`</sub>
 
@@ -501,6 +507,7 @@ interface CustomGroupDefinition {
   groupName: string
   type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
   order?: 'asc' | 'desc'
+  fallbackSort?: { type: string; order?: 'asc' | 'desc' }
   sortBy?: 'name' | 'value'
   newlinesInside?: 'always' | 'never'
   selector?: string
@@ -519,6 +526,7 @@ interface CustomGroupAnyOfDefinition {
   groupName: string
   type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
   order?: 'asc' | 'desc'
+  fallbackSort?: { type: string; order?: 'asc' | 'desc' }
   sortBy?: 'name' | 'value'
   newlinesInside?: 'always' | 'never'
   anyOf: Array<{
@@ -541,6 +549,7 @@ An object type will match a `CustomGroupAnyOfDefinition` group if it matches all
 - `elementValuePattern`: Only for properties. If entered, will check that the value of the property matches the pattern entered.
 - `type`: Overrides the sort type for that custom group. `unsorted` will not sort the group.
 - `order`: Overrides the sort order for that custom group
+- `fallbackSort`: Overrides the fallbackSort option for that custom group
 - `sortBy`: Overrides the `sortBy` option for that custom group
 - `newlinesInside`: Enforces a specific newline behavior between elements of the group.
 
diff --git a/docs/content/rules/sort-objects.mdx b/docs/content/rules/sort-objects.mdx
index b1e8d8d..3365ed4 100644
--- a/docs/content/rules/sort-objects.mdx
+++ b/docs/content/rules/sort-objects.mdx
@@ -177,7 +177,13 @@ Determines whether the sorted items should be in ascending or descending order.
 ### fallbackSort
 
 <sub>
-  type: `{ type: string; order?: 'asc' | 'desc' }`
+  type:
+  ```
+  {
+    type: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
+    order?: 'asc' | 'desc'
+  }
+  ```
 </sub>
 <sub>default: `{ type: 'unsorted' }`</sub>
 
@@ -548,6 +554,7 @@ interface CustomGroupDefinition {
   groupName: string
   type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
   order?: 'asc' | 'desc'
+  fallbackSort?: { type: string; order?: 'asc' | 'desc' }
   newlinesInside?: 'always' | 'never'
   selector?: string
   modifiers?: string[]
@@ -565,6 +572,7 @@ interface CustomGroupAnyOfDefinition {
   groupName: string
   type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
   order?: 'asc' | 'desc'
+  fallbackSort?: { type: string; order?: 'asc' | 'desc' }
   newlinesInside?: 'always' | 'never'
   anyOf: Array<{
       selector?: string
@@ -586,6 +594,7 @@ An object will match a `CustomGroupAnyOfDefinition` group if it matches all the
 - `elementValuePattern`: Only for non-function properties. If entered, will check that the value of the property matches the pattern entered.
 - `type`: Overrides the sort type for that custom group. `unsorted` will not sort the group.
 - `order`: Overrides the sort order for that custom group
+- `fallbackSort`: Overrides the fallbackSort option for that custom group
 - `newlinesInside`: Enforces a specific newline behavior between elements of the group.
 
 #### Match importance
diff --git a/docs/content/rules/sort-sets.mdx b/docs/content/rules/sort-sets.mdx
index c890819..83d6d39 100644
--- a/docs/content/rules/sort-sets.mdx
+++ b/docs/content/rules/sort-sets.mdx
@@ -149,7 +149,13 @@ Determines whether the sorted items should be in ascending or descending order.
 ### fallbackSort
 
 <sub>
-  type: `{ type: string; order?: 'asc' | 'desc' }`
+  type:
+  ```
+  {
+    type: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
+    order?: 'asc' | 'desc'
+  }
+  ```
 </sub>
 <sub>default: `{ type: 'unsorted' }`</sub>
 
@@ -330,6 +336,7 @@ interface CustomGroupDefinition {
   groupName: string
   type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
   order?: 'asc' | 'desc'
+  fallbackSort?: { type: string; order?: 'asc' | 'desc' }
   selector?: string
   elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
 }
@@ -344,6 +351,7 @@ interface CustomGroupAnyOfDefinition {
   groupName: string
   type?: 'alphabetical' | 'natural' | 'line-length' | 'unsorted'
   order?: 'asc' | 'desc'
+  fallbackSort?: { type: string; order?: 'asc' | 'desc' }
   anyOf: Array<{
       selector?: string
       elementNamePattern?: string | string[] | { pattern: string; flags?: string } | { pattern: string; flags?: string }[]
@@ -360,6 +368,7 @@ A set element will match a `CustomGroupAnyOfDefinition` group if it matches all
 - `elementNamePattern`: If entered, will check that the name of the element matches the pattern entered.
 - `type`: Overrides the sort type for that custom group. `unsorted` will not sort the group.
 - `order`: Overrides the sort order for that custom group
+- `fallbackSort`: Overrides the fallbackSort option for that custom group
 
 #### Match importance
 
diff --git a/docs/content/rules/sort-switch-case.mdx b/docs/content/rules/sort-switch-case.mdx
index 641077b..cd6ed9a 100644
--- a/docs/content/rules/sort-switch-case.mdx
+++ b/docs/content/rules/sort-switch-case.mdx
@@ -170,7 +170,13 @@ Determines whether the sorted items should be in ascending or descending order.
 ### fallbackSort
 
 <sub>
-  type: `{ type: string; order?: 'asc' | 'desc' }`
+  type:
+  ```
+  {
+    type: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
+    order?: 'asc' | 'desc'
+  }
+  ```
 </sub>
 <sub>default: `{ type: 'unsorted' }`</sub>
 
diff --git a/docs/content/rules/sort-union-types.mdx b/docs/content/rules/sort-union-types.mdx
index 10d5659..ea7c8c6 100644
--- a/docs/content/rules/sort-union-types.mdx
+++ b/docs/content/rules/sort-union-types.mdx
@@ -118,7 +118,13 @@ Determines whether the sorted items should be in ascending or descending order.
 ### fallbackSort
 
 <sub>
-  type: `{ type: string; order?: 'asc' | 'desc' }`
+  type:
+  ```
+  {
+    type: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
+    order?: 'asc' | 'desc'
+  }
+  ```
 </sub>
 <sub>default: `{ type: 'unsorted' }`</sub>
 
diff --git a/docs/content/rules/sort-variable-declarations.mdx b/docs/content/rules/sort-variable-declarations.mdx
index 7635aee..9dbc276 100644
--- a/docs/content/rules/sort-variable-declarations.mdx
+++ b/docs/content/rules/sort-variable-declarations.mdx
@@ -102,7 +102,13 @@ Determines whether the sorted items should be in ascending or descending order.
 ### fallbackSort
 
 <sub>
-  type: `{ type: string; order?: 'asc' | 'desc' }`
+  type:
+  ```
+  {
+    type: 'alphabetical' | 'natural' | 'line-length' | 'custom' | 'unsorted'
+    order?: 'asc' | 'desc'
+  }
+  ```
 </sub>
 <sub>default: `{ type: 'unsorted' }`</sub>
 
diff --git a/rules/sort-array-includes.ts b/rules/sort-array-includes.ts
index 219bc23..c27513a 100644
--- a/rules/sort-array-includes.ts
+++ b/rules/sort-array-includes.ts
@@ -22,13 +22,13 @@ import {
   ORDER_ERROR,
 } from '../utils/report-errors'
 import { validateNewlinesAndPartitionConfiguration } from '../utils/validate-newlines-and-partition-configuration'
+import { buildGetCustomGroupOverriddenOptionsFunction } from '../utils/get-custom-groups-compare-options'
 import { validateGeneratedGroupsConfiguration } from '../utils/validate-generated-groups-configuration'
 import { validateCustomSortConfiguration } from '../utils/validate-custom-sort-configuration'
 import {
   singleCustomGroupJsonSchema,
   allSelectors,
 } from './sort-array-includes/types'
-import { getCustomGroupsCompareOptions } from '../utils/get-custom-groups-compare-options'
 import { doesCustomGroupMatch } from './sort-array-includes/does-custom-group-match'
 import { getMatchingContextOptions } from '../utils/get-matching-context-options'
 import { generatePredefinedGroups } from '../utils/generate-predefined-groups'
@@ -292,10 +292,12 @@ export let sortArray = <MessageIds extends string>({
       ignoreEslintDisabledNodes: boolean,
     ): SortArrayIncludesSortingNode[] =>
       filteredGroupKindNodes.flatMap(groupedNodes =>
-        sortNodesByGroups(groupedNodes, options, {
-          getGroupCompareOptions: groupNumber =>
-            getCustomGroupsCompareOptions(options, groupNumber),
+        sortNodesByGroups({
+          getOptionsByGroupNumber:
+            buildGetCustomGroupOverriddenOptionsFunction(options),
           ignoreEslintDisabledNodes,
+          groups: options.groups,
+          nodes: groupedNodes,
         }),
       )
 
diff --git a/rules/sort-classes.ts b/rules/sort-classes.ts
index 9d673ef..2278ee9 100644
--- a/rules/sort-classes.ts
+++ b/rules/sort-classes.ts
@@ -25,6 +25,7 @@ import {
   ORDER_ERROR,
 } from '../utils/report-errors'
 import { validateNewlinesAndPartitionConfiguration } from '../utils/validate-newlines-and-partition-configuration'
+import { buildGetCustomGroupOverriddenOptionsFunction } from '../utils/get-custom-groups-compare-options'
 import { validateGeneratedGroupsConfiguration } from '../utils/validate-generated-groups-configuration'
 import {
   singleCustomGroupJsonSchema,
@@ -32,7 +33,6 @@ import {
   allSelectors,
 } from './sort-classes/types'
 import { validateCustomSortConfiguration } from '../utils/validate-custom-sort-configuration'
-import { getCustomGroupsCompareOptions } from '../utils/get-custom-groups-compare-options'
 import { getOverloadSignatureGroups } from './sort-classes/get-overload-signature-groups'
 import { generatePredefinedGroups } from '../utils/generate-predefined-groups'
 import { sortNodesByDependencies } from '../utils/sort-nodes-by-dependencies'
@@ -602,23 +602,25 @@ export default createEslintRule<SortClassesOptions, MESSAGE_ID>({
 
       let sortNodesExcludingEslintDisabled = (
         ignoreEslintDisabledNodes: boolean,
-      ): SortClassSortingNodes[] =>
-        sortNodesByDependencies(
-          formattedNodes.flatMap(nodes =>
-            sortNodesByGroups(nodes, options, {
-              isNodeIgnored: sortingNode =>
-                getGroupNumber(options.groups, sortingNode) ===
-                options.groups.length,
-              getGroupCompareOptions: groupNumber =>
-                getCustomGroupsCompareOptions(options, groupNumber),
-              ignoreEslintDisabledNodes,
-            }),
-          ),
-          {
+      ): SortClassSortingNodes[] => {
+        let nodesSortedByGroups = formattedNodes.flatMap(nodes =>
+          sortNodesByGroups({
+            isNodeIgnored: sortingNode =>
+              getGroupNumber(options.groups, sortingNode) ===
+              options.groups.length,
+            getOptionsByGroupNumber:
+              buildGetCustomGroupOverriddenOptionsFunction(options),
             ignoreEslintDisabledNodes,
-          },
+            groups: options.groups,
+            nodes,
+          }),
         )
 
+        return sortNodesByDependencies(nodesSortedByGroups, {
+          ignoreEslintDisabledNodes,
+        })
+      }
+
       let nodes = formattedNodes.flat()
 
       reportAllErrors<MESSAGE_ID, SortClassSortingNodes>({
diff --git a/rules/sort-decorators.ts b/rules/sort-decorators.ts
index 909cbe4..69f32cf 100644
--- a/rules/sort-decorators.ts
+++ b/rules/sort-decorators.ts
@@ -240,7 +240,12 @@ let sortDecorators = (
     ignoreEslintDisabledNodes: boolean,
   ): SortDecoratorsSortingNode[] =>
     formattedMembers.flatMap(nodes =>
-      sortNodesByGroups(nodes, options, { ignoreEslintDisabledNodes }),
+      sortNodesByGroups({
+        getOptionsByGroupNumber: () => ({ options }),
+        ignoreEslintDisabledNodes,
+        groups: options.groups,
+        nodes,
+      }),
     )
   let nodes = formattedMembers.flat()
 
diff --git a/rules/sort-enums.ts b/rules/sort-enums.ts
index 5964a68..ccf83ab 100644
--- a/rules/sort-enums.ts
+++ b/rules/sort-enums.ts
@@ -1,7 +1,8 @@
 import type { TSESTree } from '@typescript-eslint/types'
 
 import type { SortingNodeWithDependencies } from '../utils/sort-nodes-by-dependencies'
-import type { CompareOptions } from '../utils/compare'
+import type { NodeValueGetterFunction } from '../utils/compare'
+import type { TypeOption } from '../types/common-options'
 import type { Options } from './sort-enums/types'
 
 import {
@@ -23,7 +24,7 @@ import {
 import { validateNewlinesAndPartitionConfiguration } from '../utils/validate-newlines-and-partition-configuration'
 import { validateGeneratedGroupsConfiguration } from '../utils/validate-generated-groups-configuration'
 import { validateCustomSortConfiguration } from '../utils/validate-custom-sort-configuration'
-import { getCustomGroupsCompareOptions } from '../utils/get-custom-groups-compare-options'
+import { getCustomGroupOverriddenOptions } from '../utils/get-custom-groups-compare-options'
 import { sortNodesByDependencies } from '../utils/sort-nodes-by-dependencies'
 import { getEslintDisabledLines } from '../utils/get-eslint-disabled-lines'
 import { doesCustomGroupMatch } from './sort-enums/does-custom-group-match'
@@ -211,45 +212,40 @@ export default createEslintRule<Options, MESSAGE_ID>({
           !Number.isNaN(sortingNode.numericValue),
       )
 
-      let compareOptions: CompareOptions<SortEnumsSortingNode> &
-        Required<Options[0]> = {
+      let nodeValueGetter = computeNodeValueGetter({
+        isNumericEnum,
+        options,
+      })
+      let overriddenOptions = {
         ...options,
-        // Get the enum value rather than the name if needed.
-        nodeValueGetter:
-          options.sortByValue || (isNumericEnum && options.forceNumericSort)
-            ? sortingNode => {
-                if (isNumericEnum) {
-                  return sortingNode.numericValue!.toString()
-                }
-                return sortingNode.value ?? ''
-              }
-            : null,
-        /**
-         * If the enum is numeric, and we sort by value, always use the
-         * `natural` sort type, which will correctly sort them.
-         */
-        type:
-          isNumericEnum && (options.forceNumericSort || options.sortByValue)
-            ? 'natural'
-            : options.type,
+        type: computeOptionType({
+          isNumericEnum,
+          options,
+        }),
       }
-
       let sortNodesExcludingEslintDisabled = (
         ignoreEslintDisabledNodes: boolean,
-      ): SortEnumsSortingNode[] =>
-        sortNodesByDependencies(
-          formattedMembers.flatMap(sortingNodes =>
-            sortNodesByGroups(sortingNodes, compareOptions, {
-              getGroupCompareOptions: groupNumber =>
-                getCustomGroupsCompareOptions(compareOptions, groupNumber),
-              ignoreEslintDisabledNodes,
+      ): SortEnumsSortingNode[] => {
+        let nodesSortedByGroups = formattedMembers.flatMap(sortingNodes =>
+          sortNodesByGroups({
+            getOptionsByGroupNumber: groupNumber => ({
+              options: getCustomGroupOverriddenOptions({
+                options: overriddenOptions,
+                groupNumber,
+              }),
+              nodeValueGetter,
             }),
-          ),
-          {
             ignoreEslintDisabledNodes,
-          },
+            groups: options.groups,
+            nodes: sortingNodes,
+          }),
         )
 
+        return sortNodesByDependencies(nodesSortedByGroups, {
+          ignoreEslintDisabledNodes,
+        })
+      }
+
       reportAllErrors<MESSAGE_ID>({
         availableMessageIds: {
           missedSpacingBetweenMembers: 'missedSpacingBetweenEnumsMembers',
@@ -389,3 +385,38 @@ let getBinaryExpressionNumberValue = (
       return Number.NaN
   }
 }
+
+let computeNodeValueGetter = ({
+  isNumericEnum,
+  options,
+}: {
+  options: Pick<Required<Options[0]>, 'forceNumericSort' | 'sortByValue'>
+  isNumericEnum: boolean
+}): NodeValueGetterFunction<SortEnumsSortingNode> | null =>
+  // Get the enum value rather than the name if needed.
+  options.sortByValue || (isNumericEnum && options.forceNumericSort)
+    ? sortingNode => {
+        if (isNumericEnum) {
+          return sortingNode.numericValue!.toString()
+        }
+        return sortingNode.value ?? ''
+      }
+    : null
+
+let computeOptionType = ({
+  isNumericEnum,
+  options,
+}: {
+  options: Pick<
+    Required<Options[0]>,
+    'forceNumericSort' | 'sortByValue' | 'type'
+  >
+  isNumericEnum: boolean
+}): TypeOption =>
+  /**
+   * If the enum is numeric, and we sort by value, always use the
+   * `natural` sort type, which will correctly sort them.
+   */
+  isNumericEnum && (options.forceNumericSort || options.sortByValue)
+    ? 'natural'
+    : options.type
diff --git a/rules/sort-exports.ts b/rules/sort-exports.ts
index fb5cbd9..d1f2a8c 100644
--- a/rules/sort-exports.ts
+++ b/rules/sort-exports.ts
@@ -122,8 +122,10 @@ export default createEslintRule<Options, MESSAGE_ID>({
             ignoreEslintDisabledNodes: boolean,
           ): SortExportsSortingNode[] =>
             filteredGroupKindNodes.flatMap(groupedNodes =>
-              sortNodes(groupedNodes, options, {
+              sortNodes({
                 ignoreEslintDisabledNodes,
+                nodes: groupedNodes,
+                options,
               }),
             )
 
diff --git a/rules/sort-heritage-clauses.ts b/rules/sort-heritage-clauses.ts
index 73b95e4..2ff5a95 100644
--- a/rules/sort-heritage-clauses.ts
+++ b/rules/sort-heritage-clauses.ts
@@ -140,7 +140,12 @@ let sortHeritageClauses = (
   let sortNodesExcludingEslintDisabled = (
     ignoreEslintDisabledNodes: boolean,
   ): SortingNode[] =>
-    sortNodesByGroups(nodes, options, { ignoreEslintDisabledNodes })
+    sortNodesByGroups({
+      getOptionsByGroupNumber: () => ({ options }),
+      ignoreEslintDisabledNodes,
+      groups: options.groups,
+      nodes,
+    })
 
   reportAllErrors<MESSAGE_ID>({
     availableMessageIds: {
diff --git a/rules/sort-imports.ts b/rules/sort-imports.ts
index ba51d36..46f7228 100644
--- a/rules/sort-imports.ts
+++ b/rules/sort-imports.ts
@@ -504,21 +504,26 @@ export default createEslintRule<Options, MESSAGE_ID>({
           let sortNodesExcludingEslintDisabled = (
             ignoreEslintDisabledNodes: boolean,
           ): SortImportsSortingNode[] =>
-            sortNodesByGroups(nodes, options, {
-              getGroupCompareOptions: groupNumber => {
+            sortNodesByGroups({
+              getOptionsByGroupNumber: groupNumber => {
                 if (options.sortSideEffects) {
-                  return options
+                  return {
+                    options,
+                  }
                 }
-                let group = options.groups[groupNumber]
                 return {
-                  ...options,
-                  type: isSideEffectOnlyGroup(group)
-                    ? 'unsorted'
-                    : options.type,
+                  options: {
+                    ...options,
+                    type: isSideEffectOnlyGroup(options.groups[groupNumber])
+                      ? 'unsorted'
+                      : options.type,
+                  },
                 }
               },
               isNodeIgnored: node => node.isIgnored,
               ignoreEslintDisabledNodes,
+              groups: options.groups,
+              nodes,
             })
 
           reportAllErrors<MESSAGE_ID>({
diff --git a/rules/sort-jsx-props.ts b/rules/sort-jsx-props.ts
index 86f0f32..0a055bb 100644
--- a/rules/sort-jsx-props.ts
+++ b/rules/sort-jsx-props.ts
@@ -188,7 +188,12 @@ export default createEslintRule<Options, MESSAGE_ID>({
         let sortNodesExcludingEslintDisabled = (
           ignoreEslintDisabledNodes: boolean,
         ): SortingNode[] =>
-          sortNodesByGroups(nodes, options, { ignoreEslintDisabledNodes })
+          sortNodesByGroups({
+            getOptionsByGroupNumber: () => ({ options }),
+            ignoreEslintDisabledNodes,
+            groups: options.groups,
+            nodes,
+          })
 
         reportAllErrors<MESSAGE_ID>({
           availableMessageIds: {
diff --git a/rules/sort-maps.ts b/rules/sort-maps.ts
index 9140b7b..8da76f6 100644
--- a/rules/sort-maps.ts
+++ b/rules/sort-maps.ts
@@ -19,9 +19,9 @@ import {
   GROUP_ORDER_ERROR,
   ORDER_ERROR,
 } from '../utils/report-errors'
+import { buildGetCustomGroupOverriddenOptionsFunction } from '../utils/get-custom-groups-compare-options'
 import { validateGeneratedGroupsConfiguration } from '../utils/validate-generated-groups-configuration'
 import { validateCustomSortConfiguration } from '../utils/validate-custom-sort-configuration'
-import { getCustomGroupsCompareOptions } from '../utils/get-custom-groups-compare-options'
 import { getMatchingContextOptions } from '../utils/get-matching-context-options'
 import { getEslintDisabledLines } from '../utils/get-eslint-disabled-lines'
 import { doesCustomGroupMatch } from './sort-maps/does-custom-group-match'
@@ -173,10 +173,12 @@ export default createEslintRule<Options, MESSAGE_ID>({
           let sortNodesExcludingEslintDisabled = (
             ignoreEslintDisabledNodes: boolean,
           ): SortingNode[] =>
-            sortNodesByGroups(nodes, options, {
-              getGroupCompareOptions: groupNumber =>
-                getCustomGroupsCompareOptions(options, groupNumber),
+            sortNodesByGroups({
+              getOptionsByGroupNumber:
+                buildGetCustomGroupOverriddenOptionsFunction(options),
               ignoreEslintDisabledNodes,
+              groups: options.groups,
+              nodes,
             })
 
           reportAllErrors<MESSAGE_ID>({
diff --git a/rules/sort-modules.ts b/rules/sort-modules.ts
index 393a13a..a9a8ba5 100644
--- a/rules/sort-modules.ts
+++ b/rules/sort-modules.ts
@@ -26,6 +26,7 @@ import {
   ORDER_ERROR,
 } from '../utils/report-errors'
 import { validateNewlinesAndPartitionConfiguration } from '../utils/validate-newlines-and-partition-configuration'
+import { buildGetCustomGroupOverriddenOptionsFunction } from '../utils/get-custom-groups-compare-options'
 import { validateGeneratedGroupsConfiguration } from '../utils/validate-generated-groups-configuration'
 import {
   singleCustomGroupJsonSchema,
@@ -33,7 +34,6 @@ import {
   allSelectors,
 } from './sort-modules/types'
 import { validateCustomSortConfiguration } from '../utils/validate-custom-sort-configuration'
-import { getCustomGroupsCompareOptions } from '../utils/get-custom-groups-compare-options'
 import { generatePredefinedGroups } from '../utils/generate-predefined-groups'
 import { sortNodesByDependencies } from '../utils/sort-nodes-by-dependencies'
 import { doesCustomGroupMatch } from './sort-modules/does-custom-group-match'
@@ -346,22 +346,23 @@ let analyzeModule = ({
 
   let sortNodesExcludingEslintDisabled = (
     ignoreEslintDisabledNodes: boolean,
-  ): SortingNodeWithDependencies[] =>
-    sortNodesByDependencies(
-      formattedNodes.flatMap(nodes =>
-        sortNodesByGroups(nodes, options, {
-          isNodeIgnored: sortingNode =>
-            getGroupNumber(options.groups, sortingNode) ===
-            options.groups.length,
-          getGroupCompareOptions: groupNumber =>
-            getCustomGroupsCompareOptions(options, groupNumber),
-          ignoreEslintDisabledNodes,
-        }),
-      ),
-      {
+  ): SortingNodeWithDependencies[] => {
+    let nodesSortedByGroups = formattedNodes.flatMap(nodes =>
+      sortNodesByGroups({
+        isNodeIgnored: sortingNode =>
+          getGroupNumber(options.groups, sortingNode) === options.groups.length,
+        getOptionsByGroupNumber:
+          buildGetCustomGroupOverriddenOptionsFunction(options),
         ignoreEslintDisabledNodes,
-      },
+        groups: options.groups,
+        nodes,
+      }),
     )
+
+    return sortNodesByDependencies(nodesSortedByGroups, {
+      ignoreEslintDisabledNodes,
+    })
+  }
   let nodes = formattedNodes.flat()
 
   reportAllErrors<MESSAGE_ID>({
diff --git a/rules/sort-named-exports.ts b/rules/sort-named-exports.ts
index b9a8726..1c4db82 100644
--- a/rules/sort-named-exports.ts
+++ b/rules/sort-named-exports.ts
@@ -141,8 +141,10 @@ export default createEslintRule<Options, MESSAGE_ID>({
           ignoreEslintDisabledNodes: boolean,
         ): SortNamedExportsSortingNode[] =>
           filteredGroupKindNodes.flatMap(groupedNodes =>
-            sortNodes(groupedNodes, options, {
+            sortNodes({
               ignoreEslintDisabledNodes,
+              nodes: groupedNodes,
+              options,
             }),
           )
 
diff --git a/rules/sort-named-imports.ts b/rules/sort-named-imports.ts
index 29694ca..ada1e60 100644
--- a/rules/sort-named-imports.ts
+++ b/rules/sort-named-imports.ts
@@ -139,8 +139,10 @@ export default createEslintRule<Options, MESSAGE_ID>({
           ignoreEslintDisabledNodes: boolean,
         ): SortNamedImportsSortingNode[] =>
           filteredGroupKindNodes.flatMap(groupedNodes =>
-            sortNodes(groupedNodes, options, {
+            sortNodes({
               ignoreEslintDisabledNodes,
+              nodes: groupedNodes,
+              options,
             }),
           )
 
diff --git a/rules/sort-object-types.ts b/rules/sort-object-types.ts
index e8a263e..0e82670 100644
--- a/rules/sort-object-types.ts
+++ b/rules/sort-object-types.ts
@@ -9,7 +9,6 @@ import type {
   Selector,
   Options,
 } from './sort-object-types/types'
-import type { CompareOptions } from '../utils/compare'
 
 import {
   buildUseConfigurationIfJsonSchema,
@@ -38,7 +37,6 @@ import { validateGeneratedGroupsConfiguration } from '../utils/validate-generate
 import { getCustomGroupsCompareOptions } from './sort-object-types/get-custom-groups-compare-options'
 import { validateCustomSortConfiguration } from '../utils/validate-custom-sort-configuration'
 import { doesCustomGroupMatch } from './sort-object-types/does-custom-group-match'
-import { buildNodeValueGetter } from './sort-object-types/build-node-value-getter'
 import { getMatchingContextOptions } from '../utils/get-matching-context-options'
 import { generatePredefinedGroups } from '../utils/generate-predefined-groups'
 import { getEslintDisabledLines } from '../utils/get-eslint-disabled-lines'
@@ -359,25 +357,31 @@ export let sortObjectTypeElements = <MessageIds extends string>({
       ),
     )
 
-    let compareOptions: CompareOptions<SortObjectTypesSortingNode> &
-      Required<Options[0]> = {
-      ...options,
-      nodeValueGetter: buildNodeValueGetter(options.sortBy),
-    }
     let sortNodesExcludingEslintDisabled = (
       ignoreEslintDisabledNodes: boolean,
     ): SortObjectTypesSortingNode[] =>
       filteredGroupKindNodes.flatMap(groupedNodes =>
-        sortNodesByGroups(groupedNodes, compareOptions, {
-          isNodeIgnoredForGroup: (node, groupCompareOptions) => {
-            if (groupCompareOptions.sortBy === 'value') {
+        sortNodesByGroups({
+          getOptionsByGroupNumber: groupNumber => {
+            let { options: overriddenOptions, nodeValueGetter } =
+              getCustomGroupsCompareOptions(options, groupNumber)
+            return {
+              options: {
+                ...options,
+                ...overriddenOptions,
+              },
+              nodeValueGetter,
+            }
+          },
+          isNodeIgnoredForGroup: (node, groupOptions) => {
+            if (groupOptions.sortBy === 'value') {
               return !node.value
             }
             return false
           },
-          getGroupCompareOptions: groupNumber =>
-            getCustomGroupsCompareOptions(compareOptions, groupNumber),
           ignoreEslintDisabledNodes,
+          groups: options.groups,
+          nodes: groupedNodes,
         }),
       )
 
diff --git a/rules/sort-object-types/build-node-value-getter.ts b/rules/sort-object-types/build-node-value-getter.ts
index e2feb89..646810c 100644
--- a/rules/sort-object-types/build-node-value-getter.ts
+++ b/rules/sort-object-types/build-node-value-getter.ts
@@ -1,6 +1,7 @@
+import type { NodeValueGetterFunction } from '../../utils/compare'
 import type { SortObjectTypesSortingNode } from './types'
 
 export let buildNodeValueGetter = (
   sortBy: 'value' | 'name',
-): ((node: SortObjectTypesSortingNode) => string) | null =>
+): NodeValueGetterFunction<SortObjectTypesSortingNode> | null =>
   sortBy === 'value' ? node => node.value ?? '' : null
diff --git a/rules/sort-object-types/get-custom-groups-compare-options.ts b/rules/sort-object-types/get-custom-groups-compare-options.ts
index 03fdb02..ae3bc95 100644
--- a/rules/sort-object-types/get-custom-groups-compare-options.ts
+++ b/rules/sort-object-types/get-custom-groups-compare-options.ts
@@ -1,32 +1,47 @@
+import type { NodeValueGetterFunction } from '../../utils/compare'
 import type { SortObjectTypesSortingNode, Options } from './types'
-import type { CompareOptions } from '../../utils/compare'
 
+import { getCustomGroupsCompareOptions as baseGetCustomGroupsCompareOptions } from '../../utils/get-custom-groups-compare-options'
 import { buildNodeValueGetter } from './build-node-value-getter'
 
+type InputOptions = Pick<
+  Required<Options[0]>,
+  'fallbackSort' | 'customGroups' | 'sortBy' | 'groups' | 'order' | 'type'
+>
+
 export let getCustomGroupsCompareOptions = (
-  options: Required<Options[0]>,
+  options: InputOptions,
   groupNumber: number,
-): CompareOptions<SortObjectTypesSortingNode> & Required<Options[0]> => {
-  if (!Array.isArray(options.customGroups)) {
-    return options
-  }
-  let group = options.groups[groupNumber]
-  let customGroup =
-    typeof group === 'string'
-      ? options.customGroups.find(
-          currentGroup => group === currentGroup.groupName,
-        )
-      : null
+): {
+  options: Pick<
+    Required<Options[0]>,
+    'fallbackSort' | 'sortBy' | 'order' | 'type'
+  >
+  nodeValueGetter?: NodeValueGetterFunction<SortObjectTypesSortingNode> | null
+} => {
+  let baseCompareOptions = baseGetCustomGroupsCompareOptions(
+    options,
+    groupNumber,
+  )
 
-  let sortBy =
-    customGroup && 'sortBy' in customGroup ? customGroup.sortBy : options.sortBy
-  sortBy ??= options.sortBy
+  let { customGroups, sortBy, groups } = options
+  if (Array.isArray(customGroups)) {
+    let group = groups[groupNumber]
+    let customGroup =
+      typeof group === 'string'
+        ? customGroups.find(currentGroup => group === currentGroup.groupName)
+        : null
+
+    if (customGroup && 'sortBy' in customGroup && customGroup.sortBy) {
+      ;({ sortBy } = customGroup)
+    }
+  }
 
   return {
-    ...options,
+    options: {
+      ...baseCompareOptions,
+      sortBy,
+    },
     nodeValueGetter: buildNodeValueGetter(sortBy),
-    order: customGroup?.order ?? options.order,
-    type: customGroup?.type ?? options.type,
-    sortBy,
   }
 }
diff --git a/rules/sort-objects.ts b/rules/sort-objects.ts
index e72985a..79d16d0 100644
--- a/rules/sort-objects.ts
+++ b/rules/sort-objects.ts
@@ -1,6 +1,7 @@
 import { TSESTree } from '@typescript-eslint/types'
 
 import type { SortingNodeWithDependencies } from '../utils/sort-nodes-by-dependencies'
+import type { BaseSortNodesByGroupsOptions } from '../utils/sort-nodes-by-groups'
 import type { Modifier, Selector, Options } from './sort-objects/types'
 
 import {
@@ -22,6 +23,7 @@ import {
   ORDER_ERROR,
 } from '../utils/report-errors'
 import { validateNewlinesAndPartitionConfiguration } from '../utils/validate-newlines-and-partition-configuration'
+import { buildGetCustomGroupOverriddenOptionsFunction } from '../utils/get-custom-groups-compare-options'
 import { validateGeneratedGroupsConfiguration } from '../utils/validate-generated-groups-configuration'
 import {
   singleCustomGroupJsonSchema,
@@ -30,7 +32,6 @@ import {
 } from './sort-objects/types'
 import { validateCustomSortConfiguration } from '../utils/validate-custom-sort-configuration'
 import { getFirstNodeParentWithType } from './sort-objects/get-first-node-parent-with-type'
-import { getCustomGroupsCompareOptions } from '../utils/get-custom-groups-compare-options'
 import { getMatchingContextOptions } from '../utils/get-matching-context-options'
 import { generatePredefinedGroups } from '../utils/generate-predefined-groups'
 import { sortNodesByDependencies } from '../utils/sort-nodes-by-dependencies'
@@ -396,27 +397,36 @@ export default createEslintRule<Options, MESSAGE_ID>({
         )
       let formattedMembers = formatProperties(nodeObject.properties)
 
+      let sortingOptions: BaseSortNodesByGroupsOptions = options
       let nodesSortingFunction =
         isDestructuredObject &&
         typeof options.destructuredObjects === 'object' &&
         !options.destructuredObjects.groups
-          ? sortNodes
-          : sortNodesByGroups
+          ? ('sortNodes' as const)
+          : ('sortNodesByGroups' as const)
       let sortNodesExcludingEslintDisabled = (
         ignoreEslintDisabledNodes: boolean,
-      ): SortingNodeWithDependencies[] =>
-        sortNodesByDependencies(
-          formattedMembers.flatMap(nodes =>
-            nodesSortingFunction(nodes, options, {
-              getGroupCompareOptions: groupNumber =>
-                getCustomGroupsCompareOptions(options, groupNumber),
-              ignoreEslintDisabledNodes,
-            }),
-          ),
-          {
-            ignoreEslintDisabledNodes,
-          },
+      ): SortingNodeWithDependencies[] => {
+        let nodesSortedByGroups = formattedMembers.flatMap(nodes =>
+          nodesSortingFunction === 'sortNodes'
+            ? sortNodes({
+                ignoreEslintDisabledNodes,
+                options: sortingOptions,
+                nodes,
+              })
+            : sortNodesByGroups({
+                getOptionsByGroupNumber:
+                  buildGetCustomGroupOverriddenOptionsFunction(options),
+                ignoreEslintDisabledNodes,
+                groups: options.groups,
+                nodes,
+              }),
         )
+
+        return sortNodesByDependencies(nodesSortedByGroups, {
+          ignoreEslintDisabledNodes,
+        })
+      }
       let nodes = formattedMembers.flat()
 
       reportAllErrors<MESSAGE_ID>({
diff --git a/rules/sort-switch-case.ts b/rules/sort-switch-case.ts
index 71f5c35..fbe0c65 100644
--- a/rules/sort-switch-case.ts
+++ b/rules/sort-switch-case.ts
@@ -86,10 +86,11 @@ export default createEslintRule<Options, MESSAGE_ID>({
       // For each case group, ensure the nodes are in the correct order.
       let hasUnsortedNodes = false
       for (let caseNodesSortingNodeGroup of caseNameSortingNodeGroups) {
-        let sortedCaseNameSortingNodes = sortNodes(
-          caseNodesSortingNodeGroup,
+        let sortedCaseNameSortingNodes = sortNodes({
+          nodes: caseNodesSortingNodeGroup,
+          ignoreEslintDisabledNodes: false,
           options,
-        )
+        })
         hasUnsortedNodes ||= sortedCaseNameSortingNodes.some(
           (node, index) => node !== caseNodesSortingNodeGroup[index],
         )
@@ -220,7 +221,11 @@ export default createEslintRule<Options, MESSAGE_ID>({
           if (b.some(node => node.isDefaultClause)) {
             return -1
           }
-          return compare(a.at(0)!, b.at(0)!, options)
+          return compare({
+            a: a.at(0)!,
+            b: b.at(0)!,
+            options,
+          })
         })
         .flat()
       let sortingNodeGroupsForBlockSortFlat =
diff --git a/rules/sort-union-types.ts b/rules/sort-union-types.ts
index 3422f46..a13845a 100644
--- a/rules/sort-union-types.ts
+++ b/rules/sort-union-types.ts
@@ -274,7 +274,12 @@ export let sortUnionOrIntersectionTypes = <MessageIds extends string>({
     let sortNodesExcludingEslintDisabled = (
       ignoreEslintDisabledNodes: boolean,
     ): SortingNode[] =>
-      sortNodesByGroups(nodes, options, { ignoreEslintDisabledNodes })
+      sortNodesByGroups({
+        getOptionsByGroupNumber: () => ({ options }),
+        ignoreEslintDisabledNodes,
+        groups: options.groups,
+        nodes,
+      })
 
     reportAllErrors<MessageIds>({
       sortNodesExcludingEslintDisabled,
diff --git a/rules/sort-variable-declarations.ts b/rules/sort-variable-declarations.ts
index 0a7851a..f97ad06 100644
--- a/rules/sort-variable-declarations.ts
+++ b/rules/sort-variable-declarations.ts
@@ -213,8 +213,10 @@ export default createEslintRule<Options, MESSAGE_ID>({
       ): SortingNodeWithDependencies[] =>
         sortNodesByDependencies(
           formattedMembers.flatMap(nodes =>
-            sortNodes(nodes, options, {
+            sortNodes({
               ignoreEslintDisabledNodes,
+              options,
+              nodes,
             }),
           ),
           {
diff --git a/types/common-options.ts b/types/common-options.ts
index 5997db1..0656e95 100644
--- a/types/common-options.ts
+++ b/types/common-options.ts
@@ -1,10 +1,10 @@
 export type CustomGroupsOption<SingleCustomGroup = object> = ({
   newlinesInside?: 'always' | 'never'
+  fallbackSort?: FallbackSortOption
+  order?: OrderOption
   groupName: string
-} & (AnyOfCustomGroup<SingleCustomGroup> | SingleCustomGroup) & {
-    order?: OrderOption
-    type?: TypeOption
-  })[]
+  type?: TypeOption
+} & (AnyOfCustomGroup<SingleCustomGroup> | SingleCustomGroup))[]
 
 export interface CommonOptions {
   specialCharacters: SpecialCharactersOption
diff --git a/utils/common-json-schemas.ts b/utils/common-json-schemas.ts
index 89a08d9..09e3301 100644
--- a/utils/common-json-schemas.ts
+++ b/utils/common-json-schemas.ts
@@ -201,6 +201,7 @@ let commonCustomGroupJsonSchemas: Record<string, JSONSchema4> = {
     description: 'Custom group name.',
     type: 'string',
   },
+  fallbackSort: fallbackSortJsonSchema,
   order: orderJsonSchema,
   type: typeJsonSchema,
 }
diff --git a/utils/compare.ts b/utils/compare.ts
index 8421e9d..aecd91d 100644
--- a/utils/compare.ts
+++ b/utils/compare.ts
@@ -2,63 +2,19 @@ import { compare as createNaturalCompare } from 'natural-orderby'
 
 import type {
   SpecialCharactersOption,
-  FallbackSortOption,
-  OrderOption,
+  CommonOptions,
 } from '../types/common-options'
 import type { SortingNode } from '../types/sorting-node'
 
 import { convertBooleanToSign } from './convert-boolean-to-sign'
 
-export type CompareOptions<T extends SortingNode> =
-  | AlphabeticalCompareOptions<T>
-  | LineLengthCompareOptions<T>
-  | UnsortedCompareOptions<T>
-  | NaturalCompareOptions<T>
-  | CustomCompareOptions<T>
-
-interface BaseCompareOptions<T extends SortingNode> {
-  /**
-   * Custom function to get the value of the node. By default, returns the
-   * node's name.
-   */
-  nodeValueGetter?: ((node: T) => string) | null
-  fallbackSort: FallbackSortOption
-  order: OrderOption
-}
-
-interface AlphabeticalCompareOptions<T extends SortingNode>
-  extends BaseCompareOptions<T> {
-  specialCharacters: SpecialCharactersOption
-  locales: NonNullable<Intl.LocalesArgument>
-  type: 'alphabetical'
-  ignoreCase: boolean
-}
-
-interface NaturalCompareOptions<T extends SortingNode>
-  extends BaseCompareOptions<T> {
-  specialCharacters: SpecialCharactersOption
-  locales: NonNullable<Intl.LocalesArgument>
-  ignoreCase: boolean
-  type: 'natural'
-}
-
-interface CustomCompareOptions<T extends SortingNode>
-  extends BaseCompareOptions<T> {
-  specialCharacters: SpecialCharactersOption
-  ignoreCase: boolean
-  alphabet: string
-  type: 'custom'
-}
+export type NodeValueGetterFunction<T extends SortingNode> = (node: T) => string
 
-interface LineLengthCompareOptions<T extends SortingNode>
-  extends BaseCompareOptions<T> {
-  maxLineLength?: number
-  type: 'line-length'
-}
-
-interface UnsortedCompareOptions<T extends SortingNode>
-  extends BaseCompareOptions<T> {
-  type: 'unsorted'
+interface CompareParameters<T extends SortingNode> {
+  options: { maxLineLength?: number } & CommonOptions
+  nodeValueGetter?: NodeValueGetterFunction<T> | null
+  a: T
+  b: T
 }
 
 type SortingFunction<T extends SortingNode> = (a: T, b: T) => number
@@ -66,13 +22,52 @@ type SortingFunction<T extends SortingNode> = (a: T, b: T) => number
 type IndexByCharacters = Map<string, number>
 let alphabetCache = new Map<string, IndexByCharacters>()
 
-export let compare = <T extends SortingNode>(
-  a: T,
-  b: T,
-  options: CompareOptions<T>,
-): number => {
+export let compare = <T extends SortingNode>({
+  nodeValueGetter,
+  options,
+  a,
+  b,
+}: CompareParameters<T>): number => {
+  let finalNodeValueGetter = nodeValueGetter ?? ((node: T) => node.name)
+  let compareValue = computeCompareValue({
+    nodeValueGetter: finalNodeValueGetter,
+    options,
+    a,
+    b,
+  })
+
+  if (compareValue) {
+    return compareValue
+  }
+
+  let { fallbackSort, order } = options
+  return computeCompareValue({
+    options: {
+      ...options,
+      fallbackSort: {
+        type: 'unsorted',
+      },
+      order: fallbackSort.order ?? order,
+      type: fallbackSort.type,
+    },
+    nodeValueGetter: finalNodeValueGetter,
+    a,
+    b,
+  })
+}
+
+let computeCompareValue = <T extends SortingNode>({
+  nodeValueGetter,
+  options,
+  a,
+  b,
+}: {
+  options: { maxLineLength?: number } & CommonOptions
+  nodeValueGetter: NodeValueGetterFunction<T>
+  a: T
+  b: T
+}): number => {
   let sortingFunction: SortingFunction<T>
-  let nodeValueGetter = options.nodeValueGetter ?? ((node: T) => node.name)
 
   switch (options.type) {
     case 'alphabetical':
@@ -91,27 +86,16 @@ export let compare = <T extends SortingNode>(
       break
   }
 
-  let compareValue =
-    convertBooleanToSign(options.order === 'asc') * sortingFunction(a, b)
-
-  if (compareValue) {
-    return compareValue
-  }
-
-  let { fallbackSort, order } = options
-  return compare(a, b, {
-    ...options,
-    fallbackSort: {
-      type: 'unsorted',
-    },
-    order: fallbackSort.order ?? order,
-    type: fallbackSort.type,
-  } as CompareOptions<T>)
+  return convertBooleanToSign(options.order === 'asc') * sortingFunction(a, b)
 }
 
 let getAlphabeticalSortingFunction = <T extends SortingNode>(
-  { specialCharacters, ignoreCase, locales }: AlphabeticalCompareOptions<T>,
-  nodeValueGetter: (node: T) => string,
+  {
+    specialCharacters,
+    ignoreCase,
+    locales,
+  }: Pick<CommonOptions, 'specialCharacters' | 'ignoreCase' | 'locales'>,
+  nodeValueGetter: NodeValueGetterFunction<T>,
 ): SortingFunction<T> => {
   let formatString = getFormatStringFunction(ignoreCase, specialCharacters)
   return (aNode: T, bNode: T) =>
@@ -122,8 +106,12 @@ let getAlphabeticalSortingFunction = <T extends SortingNode>(
 }
 
 let getNaturalSortingFunction = <T extends SortingNode>(
-  { specialCharacters, ignoreCase, locales }: NaturalCompareOptions<T>,
-  nodeValueGetter: (node: T) => string,
+  {
+    specialCharacters,
+    ignoreCase,
+    locales,
+  }: Pick<CommonOptions, 'specialCharacters' | 'ignoreCase' | 'locales'>,
+  nodeValueGetter: NodeValueGetterFunction<T>,
 ): SortingFunction<T> => {
   let naturalCompare = createNaturalCompare({
     locale: locales.toString(),
@@ -137,8 +125,12 @@ let getNaturalSortingFunction = <T extends SortingNode>(
 }
 
 let getCustomSortingFunction = <T extends SortingNode>(
-  { specialCharacters, ignoreCase, alphabet }: CustomCompareOptions<T>,
-  nodeValueGetter: (node: T) => string,
+  {
+    specialCharacters,
+    ignoreCase,
+    alphabet,
+  }: Pick<CommonOptions, 'specialCharacters' | 'ignoreCase' | 'alphabet'>,
+  nodeValueGetter: NodeValueGetterFunction<T>,
 ): SortingFunction<T> => {
   let formatString = getFormatStringFunction(ignoreCase, specialCharacters)
   let indexByCharacters = alphabetCache.get(alphabet)
@@ -174,8 +166,8 @@ let getCustomSortingFunction = <T extends SortingNode>(
 
 let getLineLengthSortingFunction =
   <T extends SortingNode>(
-    { maxLineLength }: LineLengthCompareOptions<T>,
-    nodeValueGetter: (node: T) => string,
+    { maxLineLength }: { maxLineLength?: number },
+    nodeValueGetter: NodeValueGetterFunction<T>,
   ): SortingFunction<T> =>
   (aNode: T, bNode: T) => {
     let aSize = aNode.size
diff --git a/utils/get-custom-groups-compare-options.ts b/utils/get-custom-groups-compare-options.ts
index f8097cf..b246a96 100644
--- a/utils/get-custom-groups-compare-options.ts
+++ b/utils/get-custom-groups-compare-options.ts
@@ -1,43 +1,87 @@
 import type {
   DeprecatedCustomGroupsOption,
   CustomGroupsOption,
+  FallbackSortOption,
   GroupsOptions,
-  CommonOptions,
+  OrderOption,
+  TypeOption,
 } from '../types/common-options'
+import type { BaseSortNodesByGroupsOptions } from './sort-nodes-by-groups'
 
-type BaseOptions = {
+interface GroupRelatedOptions {
   customGroups: DeprecatedCustomGroupsOption | CustomGroupsOption
   groups: GroupsOptions<string>
-} & CommonOptions
+}
+
+interface OverridableOptions {
+  fallbackSort: FallbackSortOption
+  order: OrderOption
+  type: TypeOption
+}
 
 /**
  * Retrieves the compare options used to sort a given group. If the group is a
  * custom group, its options will be favored over the default options. Returns
  * `null` if the group should not be sorted.
- * @param {BaseOptions} options - The sorting options, including groups and
+ * @param {GroupRelatedOptions & OverridableOptions} options - The sorting options, including groups and
  * custom groups.
  * @param {number} groupNumber - The index of the group to retrieve compare
  * options for.
- * @returns {BaseOptions} The options for the group
+ * @returns {object} The options for the group
  */
-export let getCustomGroupsCompareOptions = <Options extends BaseOptions>(
-  options: Options,
+export let getCustomGroupsCompareOptions = (
+  options: GroupRelatedOptions & OverridableOptions,
   groupNumber: number,
-): Options => {
-  if (!Array.isArray(options.customGroups)) {
-    return options
+): OverridableOptions => {
+  let { customGroups, fallbackSort, groups, order, type } = options
+
+  if (Array.isArray(customGroups)) {
+    let group = groups[groupNumber]
+    let customGroup =
+      typeof group === 'string'
+        ? customGroups.find(currentGroup => group === currentGroup.groupName)
+        : null
+
+    if (customGroup) {
+      fallbackSort = {
+        type: customGroup.fallbackSort?.type ?? fallbackSort.type,
+      }
+      let fallbackOrder = customGroup.fallbackSort?.order ?? fallbackSort.order
+      if (fallbackOrder) {
+        fallbackSort.order = fallbackOrder
+      }
+      order = customGroup.order ?? order
+      type = customGroup.type ?? type
+    }
   }
-  let group = options.groups[groupNumber]
-  let customGroup =
-    typeof group === 'string'
-      ? options.customGroups.find(
-          currentGroup => group === currentGroup.groupName,
-        )
-      : null
 
   return {
-    ...options,
-    order: customGroup?.order ?? options.order,
-    type: customGroup?.type ?? options.type,
+    fallbackSort,
+    order,
+    type,
   }
 }
+
+export let buildGetCustomGroupOverriddenOptionsFunction =
+  (
+    options: BaseSortNodesByGroupsOptions & GroupRelatedOptions,
+  ): ((groupNumber: number) => {
+    options: BaseSortNodesByGroupsOptions
+  }) =>
+  (groupNumber: number) => ({
+    options: getCustomGroupOverriddenOptions({
+      groupNumber,
+      options,
+    }),
+  })
+
+export let getCustomGroupOverriddenOptions = ({
+  groupNumber,
+  options,
+}: {
+  options: BaseSortNodesByGroupsOptions & GroupRelatedOptions
+  groupNumber: number
+}): BaseSortNodesByGroupsOptions => ({
+  ...options,
+  ...getCustomGroupsCompareOptions(options, groupNumber),
+})
diff --git a/utils/get-settings.ts b/utils/get-settings.ts
index ecff264..0756385 100644
--- a/utils/get-settings.ts
+++ b/utils/get-settings.ts
@@ -2,6 +2,7 @@ import type { TSESLint } from '@typescript-eslint/utils'
 
 import type {
   SpecialCharactersOption,
+  FallbackSortOption,
   OrderOption,
   RegexOption,
   TypeOption,
@@ -18,6 +19,7 @@ export type Settings = Partial<{
     | string
   specialCharacters: SpecialCharactersOption
   locales: NonNullable<Intl.LocalesArgument>
+  fallbackSort: FallbackSortOption
   partitionByNewLine: boolean
   ignorePattern: RegexOption
   ignoreCase: boolean
@@ -39,6 +41,7 @@ export let getSettings = (
       'partitionByNewLine',
       'specialCharacters',
       'ignorePattern',
+      'fallbackSort',
       'ignoreCase',
       'alphabet',
       'locales',
diff --git a/utils/sort-nodes-by-groups.ts b/utils/sort-nodes-by-groups.ts
index f94779d..3d5be63 100644
--- a/utils/sort-nodes-by-groups.ts
+++ b/utils/sort-nodes-by-groups.ts
@@ -1,46 +1,51 @@
-import type { GroupsOptions } from '../types/common-options'
+import type { CommonOptions, GroupsOptions } from '../types/common-options'
+import type { NodeValueGetterFunction } from './compare'
 import type { SortingNode } from '../types/sorting-node'
-import type { CompareOptions } from './compare'
 
 import { getGroupNumber } from './get-group-number'
 import { sortNodes } from './sort-nodes'
 
-interface ExtraOptions<T extends SortingNode, Options extends BaseOptions<T>> {
-  getGroupCompareOptions?(groupNumber: number): CompareOptions<T> & Options
-
-  isNodeIgnoredForGroup?(node: T, compareOptions: Options): boolean
+export type BaseSortNodesByGroupsOptions = {
+  maxLineLength?: number
+} & CommonOptions
 
+interface SortNodesByGroupsParameters<
+  Options extends BaseSortNodesByGroupsOptions,
+  T extends SortingNode,
+> {
+  getOptionsByGroupNumber(groupNumber: number): {
+    nodeValueGetter?: NodeValueGetterFunction<T> | null
+    options: Options
+  }
+  isNodeIgnoredForGroup?(node: T, groupOptions: Options): boolean
   ignoreEslintDisabledNodes: boolean
-
   isNodeIgnored?(node: T): boolean
-}
-
-type BaseOptions<T extends SortingNode> = CompareOptions<T> & GroupsOption
-
-interface GroupsOption {
   groups: GroupsOptions<string>
+  nodes: T[]
 }
 
 export let sortNodesByGroups = <
   T extends SortingNode,
-  Options extends BaseOptions<T>,
->(
-  nodes: T[],
-  options: Options,
-  extraOptions?: ExtraOptions<T, Options>,
-): T[] => {
+  Options extends BaseSortNodesByGroupsOptions,
+>({
+  ignoreEslintDisabledNodes,
+  getOptionsByGroupNumber,
+  isNodeIgnoredForGroup,
+  isNodeIgnored,
+  groups,
+  nodes,
+}: SortNodesByGroupsParameters<Options, T>): T[] => {
   let nodesByNonIgnoredGroupNumber: Record<number, T[]> = {}
   let ignoredNodeIndices: number[] = []
   for (let [index, sortingNode] of nodes.entries()) {
     if (
-      (sortingNode.isEslintDisabled &&
-        extraOptions?.ignoreEslintDisabledNodes) ||
-      extraOptions?.isNodeIgnored?.(sortingNode)
+      (sortingNode.isEslintDisabled && ignoreEslintDisabledNodes) ||
+      isNodeIgnored?.(sortingNode)
     ) {
       ignoredNodeIndices.push(index)
       continue
     }
-    let groupNumber = getGroupNumber(options.groups, sortingNode)
+    let groupNumber = getGroupNumber(groups, sortingNode)
     nodesByNonIgnoredGroupNumber[groupNumber] ??= []
     nodesByNonIgnoredGroupNumber[groupNumber].push(sortingNode)
   }
@@ -49,20 +54,22 @@ export let sortNodesByGroups = <
   for (let groupNumber of Object.keys(nodesByNonIgnoredGroupNumber).sort(
     (a, b) => Number(a) - Number(b),
   )) {
-    let compareOptions =
-      extraOptions?.getGroupCompareOptions?.(Number(groupNumber)) ?? options
+    let { nodeValueGetter, options } = getOptionsByGroupNumber(
+      Number(groupNumber),
+    )
     let nodesToPush = nodesByNonIgnoredGroupNumber[Number(groupNumber)]!
 
     let groupIgnoredNodes = new Set(
-      nodesToPush.filter(node =>
-        extraOptions?.isNodeIgnoredForGroup?.(node, compareOptions),
-      ),
+      nodesToPush.filter(node => isNodeIgnoredForGroup?.(node, options)),
     )
 
     sortedNodes.push(
-      ...sortNodes(nodesToPush, compareOptions, {
+      ...sortNodes({
         isNodeIgnored: node => groupIgnoredNodes.has(node),
         ignoreEslintDisabledNodes: false,
+        nodes: nodesToPush,
+        nodeValueGetter,
+        options,
       }),
     )
   }
diff --git a/utils/sort-nodes.ts b/utils/sort-nodes.ts
index 17aadbe..5a4a323 100644
--- a/utils/sort-nodes.ts
+++ b/utils/sort-nodes.ts
@@ -1,26 +1,30 @@
+import type { CommonOptions } from '../types/common-options'
+import type { NodeValueGetterFunction } from './compare'
 import type { SortingNode } from '../types/sorting-node'
-import type { CompareOptions } from './compare'
 
 import { compare } from './compare'
 
-interface ExtraOptions<T extends SortingNode> {
+interface SortNodesParameters<T extends SortingNode> {
+  options: { maxLineLength?: number } & CommonOptions
+  nodeValueGetter?: NodeValueGetterFunction<T> | null
   ignoreEslintDisabledNodes: boolean
-
   isNodeIgnored?(node: T): boolean
+  nodes: T[]
 }
 
-export let sortNodes = <T extends SortingNode>(
-  nodes: T[],
-  options: CompareOptions<T>,
-  extraOptions?: ExtraOptions<T>,
-): T[] => {
+export let sortNodes = <T extends SortingNode>({
+  ignoreEslintDisabledNodes,
+  nodeValueGetter,
+  isNodeIgnored,
+  options,
+  nodes,
+}: SortNodesParameters<T>): T[] => {
   let nonIgnoredNodes: T[] = []
   let ignoredNodeIndices: number[] = []
   for (let [index, sortingNode] of nodes.entries()) {
     if (
-      (sortingNode.isEslintDisabled &&
-        extraOptions?.ignoreEslintDisabledNodes) ||
-      extraOptions?.isNodeIgnored?.(sortingNode)
+      (sortingNode.isEslintDisabled && ignoreEslintDisabledNodes) ||
+      isNodeIgnored?.(sortingNode)
     ) {
       ignoredNodeIndices.push(index)
     } else {
@@ -28,7 +32,14 @@ export let sortNodes = <T extends SortingNode>(
     }
   }
 
-  let sortedNodes = [...nonIgnoredNodes].sort((a, b) => compare(a, b, options))
+  let sortedNodes = [...nonIgnoredNodes].sort((a, b) =>
+    compare({
+      nodeValueGetter,
+      options,
+      a,
+      b,
+    }),
+  )
 
   // Add ignored nodes at the same position as they were before linting.
   for (let ignoredIndex of ignoredNodeIndices) {


Test patch:
diff --git a/test/rules/sort-array-includes.test.ts b/test/rules/sort-array-includes.test.ts
index 5c67805..a72cd56 100644
--- a/test/rules/sort-array-includes.test.ts
+++ b/test/rules/sort-array-includes.test.ts
@@ -1244,6 +1244,58 @@ describe(ruleName, () => {
         },
       )
 
+      ruleTester.run(
+        `${ruleName}: sort custom groups by overriding 'fallbackSort'`,
+        rule,
+        {
+          invalid: [
+            {
+              options: [
+                {
+                  customGroups: [
+                    {
+                      fallbackSort: {
+                        type: 'alphabetical',
+                        order: 'asc',
+                      },
+                      elementNamePattern: '^foo',
+                      type: 'line-length',
+                      groupName: 'foo',
+                      order: 'desc',
+                    },
+                  ],
+                  type: 'alphabetical',
+                  groups: ['foo'],
+                  order: 'asc',
+                },
+              ],
+              errors: [
+                {
+                  data: {
+                    right: 'fooBar',
+                    left: 'fooZar',
+                  },
+                  messageId: 'unexpectedArrayIncludesOrder',
+                },
+              ],
+              output: dedent`
+                [
+                  'fooBar',
+                  'fooZar',
+                ].includes(value)
+              `,
+              code: dedent`
+                [
+                  'fooZar',
+                  'fooBar',
+                ].includes(value)
+              `,
+            },
+          ],
+          valid: [],
+        },
+      )
+
       ruleTester.run(
         `${ruleName}: does not sort custom groups with 'unsorted' type`,
         rule,
diff --git a/test/rules/sort-classes.test.ts b/test/rules/sort-classes.test.ts
index 41e8e71..7c9ea52 100644
--- a/test/rules/sort-classes.test.ts
+++ b/test/rules/sort-classes.test.ts
@@ -8020,6 +8020,58 @@ describe(ruleName, () => {
       },
     )
 
+    ruleTester.run(
+      `${ruleName}: sort custom groups by overriding 'fallbackSort'`,
+      rule,
+      {
+        invalid: [
+          {
+            options: [
+              {
+                customGroups: [
+                  {
+                    fallbackSort: {
+                      type: 'alphabetical',
+                      order: 'asc',
+                    },
+                    elementNamePattern: '^foo',
+                    type: 'line-length',
+                    groupName: 'foo',
+                    order: 'desc',
+                  },
+                ],
+                type: 'alphabetical',
+                groups: ['foo'],
+                order: 'asc',
+              },
+            ],
+            errors: [
+              {
+                data: {
+                  right: 'fooBar',
+                  left: 'fooZar',
+                },
+                messageId: 'unexpectedClassesOrder',
+              },
+            ],
+            output: dedent`
+              class Class {
+                fooBar: string
+                fooZar: string
+              }
+            `,
+            code: dedent`
+              class Class {
+                fooZar: string
+                fooBar: string
+              }
+            `,
+          },
+        ],
+        valid: [],
+      },
+    )
+
     ruleTester.run(
       `${ruleName}: does not sort custom groups with 'unsorted' type`,
       rule,
diff --git a/test/rules/sort-enums.test.ts b/test/rules/sort-enums.test.ts
index b074505..dfed469 100644
--- a/test/rules/sort-enums.test.ts
+++ b/test/rules/sort-enums.test.ts
@@ -1096,6 +1096,58 @@ describe(ruleName, () => {
         },
       )
 
+      ruleTester.run(
+        `${ruleName}: sort custom groups by overriding 'fallbackSort'`,
+        rule,
+        {
+          invalid: [
+            {
+              options: [
+                {
+                  customGroups: [
+                    {
+                      fallbackSort: {
+                        type: 'alphabetical',
+                        order: 'asc',
+                      },
+                      elementNamePattern: '^foo',
+                      type: 'line-length',
+                      groupName: 'foo',
+                      order: 'desc',
+                    },
+                  ],
+                  type: 'alphabetical',
+                  groups: ['foo'],
+                  order: 'asc',
+                },
+              ],
+              errors: [
+                {
+                  data: {
+                    right: 'fooBar',
+                    left: 'fooZar',
+                  },
+                  messageId: 'unexpectedEnumsOrder',
+                },
+              ],
+              output: dedent`
+                enum Enum {
+                  fooBar = 'fooBar',
+                  fooZar = 'fooZar',
+                }
+              `,
+              code: dedent`
+                enum Enum {
+                  fooZar = 'fooZar',
+                  fooBar = 'fooBar',
+                }
+              `,
+            },
+          ],
+          valid: [],
+        },
+      )
+
       ruleTester.run(
         `${ruleName}: does not sort custom groups with 'unsorted' type`,
         rule,
diff --git a/test/rules/sort-interfaces.test.ts b/test/rules/sort-interfaces.test.ts
index 96adf71..f34868d 100644
--- a/test/rules/sort-interfaces.test.ts
+++ b/test/rules/sort-interfaces.test.ts
@@ -1256,6 +1256,58 @@ describe(ruleName, () => {
         },
       )
 
+      ruleTester.run(
+        `${ruleName}: sort custom groups by overriding 'fallbackSort'`,
+        rule,
+        {
+          invalid: [
+            {
+              options: [
+                {
+                  customGroups: [
+                    {
+                      fallbackSort: {
+                        type: 'alphabetical',
+                        order: 'asc',
+                      },
+                      elementNamePattern: '^foo',
+                      type: 'line-length',
+                      groupName: 'foo',
+                      order: 'desc',
+                    },
+                  ],
+                  type: 'alphabetical',
+                  groups: ['foo'],
+                  order: 'asc',
+                },
+              ],
+              errors: [
+                {
+                  data: {
+                    right: 'fooBar',
+                    left: 'fooZar',
+                  },
+                  messageId: 'unexpectedInterfacePropertiesOrder',
+                },
+              ],
+              output: dedent`
+                interface Interface {
+                  fooBar: string
+                  fooZar: string
+                }
+              `,
+              code: dedent`
+                interface Interface {
+                  fooZar: string
+                  fooBar: string
+                }
+              `,
+            },
+          ],
+          valid: [],
+        },
+      )
+
       ruleTester.run(
         `${ruleName}: sort custom groups by overriding 'sortBy'`,
         rule,
diff --git a/test/rules/sort-maps.test.ts b/test/rules/sort-maps.test.ts
index 8b73a66..71b4492 100644
--- a/test/rules/sort-maps.test.ts
+++ b/test/rules/sort-maps.test.ts
@@ -925,6 +925,58 @@ describe(ruleName, () => {
         },
       )
 
+      ruleTester.run(
+        `${ruleName}: sort custom groups by overriding 'fallbackSort'`,
+        rule,
+        {
+          invalid: [
+            {
+              options: [
+                {
+                  customGroups: [
+                    {
+                      fallbackSort: {
+                        type: 'alphabetical',
+                        order: 'asc',
+                      },
+                      elementNamePattern: '^foo',
+                      type: 'line-length',
+                      groupName: 'foo',
+                      order: 'desc',
+                    },
+                  ],
+                  type: 'alphabetical',
+                  groups: ['foo'],
+                  order: 'asc',
+                },
+              ],
+              errors: [
+                {
+                  data: {
+                    right: 'fooBar',
+                    left: 'fooZar',
+                  },
+                  messageId: 'unexpectedMapElementsOrder',
+                },
+              ],
+              output: dedent`
+                new Map([
+                  [fooBar, fooBar],
+                  [fooZar, fooZar],
+                ])
+              `,
+              code: dedent`
+                new Map([
+                  [fooZar, fooZar],
+                  [fooBar, fooBar],
+                ])
+              `,
+            },
+          ],
+          valid: [],
+        },
+      )
+
       ruleTester.run(
         `${ruleName}: does not sort custom groups with 'unsorted' type`,
         rule,
diff --git a/test/rules/sort-modules.test.ts b/test/rules/sort-modules.test.ts
index c07ff81..5f75539 100644
--- a/test/rules/sort-modules.test.ts
+++ b/test/rules/sort-modules.test.ts
@@ -657,6 +657,54 @@ describe(ruleName, () => {
         },
       )
 
+      ruleTester.run(
+        `${ruleName}: sort custom groups by overriding 'fallbackSort'`,
+        rule,
+        {
+          invalid: [
+            {
+              options: [
+                {
+                  customGroups: [
+                    {
+                      fallbackSort: {
+                        type: 'alphabetical',
+                        order: 'asc',
+                      },
+                      elementNamePattern: '^foo',
+                      type: 'line-length',
+                      groupName: 'foo',
+                      order: 'desc',
+                    },
+                  ],
+                  type: 'alphabetical',
+                  groups: ['foo'],
+                  order: 'asc',
+                },
+              ],
+              errors: [
+                {
+                  data: {
+                    right: 'fooBar',
+                    left: 'fooZar',
+                  },
+                  messageId: 'unexpectedModulesOrder',
+                },
+              ],
+              output: dedent`
+                function fooBar() {}
+                function fooZar() {}
+              `,
+              code: dedent`
+                function fooZar() {}
+                function fooBar() {}
+              `,
+            },
+          ],
+          valid: [],
+        },
+      )
+
       ruleTester.run(
         `${ruleName}: does not sort custom groups with 'unsorted' type`,
         rule,
diff --git a/test/rules/sort-object-types.test.ts b/test/rules/sort-object-types.test.ts
index b49351a..bb7dc5e 100644
--- a/test/rules/sort-object-types.test.ts
+++ b/test/rules/sort-object-types.test.ts
@@ -997,6 +997,58 @@ describe(ruleName, () => {
         },
       )
 
+      ruleTester.run(
+        `${ruleName}: sort custom groups by overriding 'fallbackSort'`,
+        rule,
+        {
+          invalid: [
+            {
+              options: [
+                {
+                  customGroups: [
+                    {
+                      fallbackSort: {
+                        type: 'alphabetical',
+                        order: 'asc',
+                      },
+                      elementNamePattern: '^foo',
+                      type: 'line-length',
+                      groupName: 'foo',
+                      order: 'desc',
+                    },
+                  ],
+                  type: 'alphabetical',
+                  groups: ['foo'],
+                  order: 'asc',
+                },
+              ],
+              errors: [
+                {
+                  data: {
+                    right: 'fooBar',
+                    left: 'fooZar',
+                  },
+                  messageId: 'unexpectedObjectTypesOrder',
+                },
+              ],
+              output: dedent`
+                type Type = {
+                  fooBar: string
+                  fooZar: string
+                }
+              `,
+              code: dedent`
+                type Type = {
+                  fooZar: string
+                  fooBar: string
+                }
+              `,
+            },
+          ],
+          valid: [],
+        },
+      )
+
       ruleTester.run(
         `${ruleName}: sort custom groups by overriding 'sortBy'`,
         rule,
diff --git a/test/rules/sort-objects.test.ts b/test/rules/sort-objects.test.ts
index e65176f..2872367 100644
--- a/test/rules/sort-objects.test.ts
+++ b/test/rules/sort-objects.test.ts
@@ -2962,6 +2962,58 @@ describe(ruleName, () => {
         },
       )
 
+      ruleTester.run(
+        `${ruleName}: sort custom groups by overriding 'fallbackSort'`,
+        rule,
+        {
+          invalid: [
+            {
+              options: [
+                {
+                  customGroups: [
+                    {
+                      fallbackSort: {
+                        type: 'alphabetical',
+                        order: 'asc',
+                      },
+                      elementNamePattern: '^foo',
+                      type: 'line-length',
+                      groupName: 'foo',
+                      order: 'desc',
+                    },
+                  ],
+                  type: 'alphabetical',
+                  groups: ['foo'],
+                  order: 'asc',
+                },
+              ],
+              errors: [
+                {
+                  data: {
+                    right: 'fooBar',
+                    left: 'fooZar',
+                  },
+                  messageId: 'unexpectedObjectsOrder',
+                },
+              ],
+              output: dedent`
+                let obj = {
+                  fooBar: 'fooBar',
+                  fooZar: 'fooZar',
+                }
+              `,
+              code: dedent`
+                let obj = {
+                  fooZar: 'fooZar',
+                  fooBar: 'fooBar',
+                }
+              `,
+            },
+          ],
+          valid: [],
+        },
+      )
+
       ruleTester.run(
         `${ruleName}: does not sort custom groups with 'unsorted' type`,
         rule,
diff --git a/test/rules/sort-sets.test.ts b/test/rules/sort-sets.test.ts
index 6bc8f94..3edb10c 100644
--- a/test/rules/sort-sets.test.ts
+++ b/test/rules/sort-sets.test.ts
@@ -1191,6 +1191,58 @@ describe(ruleName, () => {
         },
       )
 
+      ruleTester.run(
+        `${ruleName}: sort custom groups by overriding 'fallbackSort'`,
+        rule,
+        {
+          invalid: [
+            {
+              options: [
+                {
+                  customGroups: [
+                    {
+                      fallbackSort: {
+                        type: 'alphabetical',
+                        order: 'asc',
+                      },
+                      elementNamePattern: '^foo',
+                      type: 'line-length',
+                      groupName: 'foo',
+                      order: 'desc',
+                    },
+                  ],
+                  type: 'alphabetical',
+                  groups: ['foo'],
+                  order: 'asc',
+                },
+              ],
+              errors: [
+                {
+                  data: {
+                    right: 'fooBar',
+                    left: 'fooZar',
+                  },
+                  messageId: 'unexpectedSetsOrder',
+                },
+              ],
+              output: dedent`
+                new Set([
+                  'fooBar',
+                  'fooZar',
+                ])
+              `,
+              code: dedent`
+                new Set([
+                  'fooZar',
+                  'fooBar',
+                ])
+              `,
+            },
+          ],
+          valid: [],
+        },
+      )
+
       ruleTester.run(
         `${ruleName}: does not sort custom groups with 'unsorted' type`,
         rule,
diff --git a/test/utils/compare.test.ts b/test/utils/compare.test.ts
index cc30175..720ea0c 100644
--- a/test/utils/compare.test.ts
+++ b/test/utils/compare.test.ts
@@ -7,131 +7,149 @@ import { compare } from '../../utils/compare'
 
 describe('compare', () => {
   describe('alphabetical', () => {
-    let compareOptions = {
+    let options = {
       fallbackSort: { type: 'unsorted' } as const,
       specialCharacters: 'keep' as const,
       type: 'alphabetical' as const,
       locales: 'en-US' as const,
       order: 'asc' as const,
       ignoreCase: false,
+      alphabet: '',
     }
 
     it('sorts by order asc', () => {
       expect(
-        compare(
-          createTestNode({ name: 'b' }),
-          createTestNode({ name: 'a' }),
-          compareOptions,
-        ),
+        compare({
+          b: createTestNode({ name: 'a' }),
+          a: createTestNode({ name: 'b' }),
+          options,
+        }),
       ).toBe(1)
     })
 
     it('sorts by order desc', () => {
       expect(
-        compare(createTestNode({ name: 'a' }), createTestNode({ name: 'b' }), {
-          ...compareOptions,
-          order: 'desc',
+        compare({
+          options: {
+            ...options,
+            order: 'desc',
+          },
+          a: createTestNode({ name: 'a' }),
+          b: createTestNode({ name: 'b' }),
         }),
       ).toBe(1)
     })
 
     it('sorts ignoring case', () => {
       expect(
-        compare(
-          createTestNode({ name: 'aB' }),
-          createTestNode({ name: 'Ab' }),
-          {
-            ...compareOptions,
+        compare({
+          options: {
+            ...options,
             ignoreCase: true,
           },
-        ),
+          a: createTestNode({ name: 'aB' }),
+          b: createTestNode({ name: 'Ab' }),
+        }),
       ).toBe(0)
     })
 
     it('sorts while trimming special characters', () => {
       expect(
-        compare(createTestNode({ name: '_a' }), createTestNode({ name: 'a' }), {
-          ...compareOptions,
-          specialCharacters: 'trim',
+        compare({
+          options: {
+            ...options,
+            specialCharacters: 'trim',
+          },
+          a: createTestNode({ name: '_a' }),
+          b: createTestNode({ name: 'a' }),
         }),
       ).toBe(0)
     })
 
     it('sorts while removing special characters', () => {
       expect(
-        compare(
-          createTestNode({ name: 'ab' }),
-          createTestNode({ name: 'a_b' }),
-          {
-            ...compareOptions,
+        compare({
+          options: {
+            ...options,
             specialCharacters: 'remove',
           },
-        ),
+          b: createTestNode({ name: 'a_b' }),
+          a: createTestNode({ name: 'ab' }),
+        }),
       ).toBe(0)
     })
   })
 
   describe('natural', () => {
-    let compareOptions = {
+    let options = {
       fallbackSort: { type: 'unsorted' } as const,
       specialCharacters: 'keep' as const,
       locales: 'en-US' as const,
       type: 'natural' as const,
       order: 'asc' as const,
       ignoreCase: false,
+      alphabet: '',
     }
 
     it('sorts by order asc', () => {
       expect(
-        compare(
-          createTestNode({ name: 'b' }),
-          createTestNode({ name: 'a' }),
-          compareOptions,
-        ),
+        compare({
+          b: createTestNode({ name: 'a' }),
+          a: createTestNode({ name: 'b' }),
+          options,
+        }),
       ).toBe(1)
     })
 
     it('sorts by order desc', () => {
       expect(
-        compare(createTestNode({ name: 'a' }), createTestNode({ name: 'b' }), {
-          ...compareOptions,
-          order: 'desc',
+        compare({
+          options: {
+            ...options,
+            order: 'desc',
+          },
+          a: createTestNode({ name: 'a' }),
+          b: createTestNode({ name: 'b' }),
         }),
       ).toBe(1)
     })
 
     it('sorts ignoring case', () => {
       expect(
-        compare(
-          createTestNode({ name: 'aB' }),
-          createTestNode({ name: 'Ab' }),
-          {
-            ...compareOptions,
+        compare({
+          options: {
+            ...options,
             ignoreCase: true,
           },
-        ),
+          a: createTestNode({ name: 'aB' }),
+          b: createTestNode({ name: 'Ab' }),
+        }),
       ).toBe(0)
     })
 
     it('sorts while trimming special characters', () => {
       expect(
-        compare(createTestNode({ name: '_a' }), createTestNode({ name: 'a' }), {
-          ...compareOptions,
-          specialCharacters: 'trim',
+        compare({
+          options: {
+            ...options,
+            specialCharacters: 'trim',
+          },
+          a: createTestNode({ name: '_a' }),
+          b: createTestNode({ name: 'a' }),
         }),
       ).toBe(0)
     })
 
     it('sorts while removing special characters', () => {
       expect(
-        compare(
-          createTestNode({ name: 'ab' }),
-          createTestNode({ name: 'a_b' }),
-          {
-            ...compareOptions,
+        compare({
+          options: {
+            ...options,
             specialCharacters: 'remove',
           },
-        ),
+          b: createTestNode({ name: 'a_b' }),
+          a: createTestNode({ name: 'ab' }),
+        }),
       ).toBe(0)
     })
   })
@@ -144,30 +162,38 @@ describe('compare', () => {
       locales: 'en-US' as const,
       order: 'desc' as const,
       ignoreCase: false,
+      alphabet: '',
     }
 
     it('sorts by order asc', () => {
       expect(
-        compare(createTestNode({ name: 'b' }), createTestNode({ name: 'aa' }), {
-          ...compareOptions,
-          order: 'asc',
+        compare({
+          options: {
+            ...compareOptions,
+            order: 'desc',
+          },
+          b: createTestNode({ name: 'aa' }),
+          a: createTestNode({ name: 'b' }),
         }),
-      ).toBe(-1)
+      ).toBe(1)
     })
 
     it('sorts by order desc', () => {
       expect(
-        compare(
-          createTestNode({ name: 'aa' }),
-          createTestNode({ name: 'b' }),
-          compareOptions,
-        ),
+        compare({
+          options: {
+            ...compareOptions,
+            order: 'desc',
+          },
+          a: createTestNode({ name: 'aa' }),
+          b: createTestNode({ name: 'b' }),
+        }),
       ).toBe(-1)
     })
   })
 
   describe('custom', () => {
-    let compareOptions = {
+    let options = {
       alphabet: Alphabet.generateRecommendedAlphabet()
         .sortByLocaleCompare('en-US')
         .getCharacters(),
@@ -181,90 +207,109 @@ describe('compare', () => {
 
     it('sorts by order asc', () => {
       expect(
-        compare(
-          createTestNode({ name: 'b' }),
-          createTestNode({ name: 'a' }),
-          compareOptions,
-        ),
+        compare({
+          b: createTestNode({ name: 'a' }),
+          a: createTestNode({ name: 'b' }),
+          options,
+        }),
       ).toBe(1)
     })
 
     it('sorts by order desc', () => {
       expect(
-        compare(createTestNode({ name: 'a' }), createTestNode({ name: 'b' }), {
-          ...compareOptions,
-          order: 'desc',
+        compare({
+          options: {
+            ...options,
+            order: 'desc',
+          },
+          a: createTestNode({ name: 'a' }),
+          b: createTestNode({ name: 'b' }),
         }),
       ).toBe(1)
     })
 
     it('sorts ignoring case', () => {
       expect(
-        compare(
-          createTestNode({ name: 'aB' }),
-          createTestNode({ name: 'Ab' }),
-          {
-            ...compareOptions,
+        compare({
+          options: {
+            ...options,
             ignoreCase: true,
           },
-        ),
+          a: createTestNode({ name: 'aB' }),
+          b: createTestNode({ name: 'Ab' }),
+        }),
       ).toBe(0)
     })
 
     it('sorts while trimming special characters', () => {
       expect(
-        compare(createTestNode({ name: '_a' }), createTestNode({ name: 'a' }), {
-          ...compareOptions,
-          specialCharacters: 'trim',
+        compare({
+          options: {
+            ...options,
+            specialCharacters: 'trim',
+          },
+          a: createTestNode({ name: '_a' }),
+          b: createTestNode({ name: 'a' }),
         }),
       ).toBe(0)
     })
 
     it('sorts while removing special characters', () => {
       expect(
-        compare(
-          createTestNode({ name: 'ab' }),
-          createTestNode({ name: 'a_b' }),
-          {
-            ...compareOptions,
+        compare({
+          options: {
+            ...options,
             specialCharacters: 'remove',
           },
-        ),
+          b: createTestNode({ name: 'a_b' }),
+          a: createTestNode({ name: 'ab' }),
+        }),
       ).toBe(0)
     })
 
     it('gives minimum priority to characters not in the alphabet', () => {
       expect(
-        compare(createTestNode({ name: 'a' }), createTestNode({ name: 'b' }), {
-          ...compareOptions,
-          alphabet: 'b',
+        compare({
+          options: {
+            ...options,
+            alphabet: 'b',
+          },
+          a: createTestNode({ name: 'a' }),
+          b: createTestNode({ name: 'b' }),
         }),
       ).toBe(1)
+
       expect(
-        compare(createTestNode({ name: 'b' }), createTestNode({ name: 'a' }), {
-          ...compareOptions,
-          alphabet: 'b',
+        compare({
+          options: {
+            ...options,
+            alphabet: 'b',
+          },
+          b: createTestNode({ name: 'a' }),
+          a: createTestNode({ name: 'b' }),
         }),
       ).toBe(-1)
-      expect(
-        compare(createTestNode({ name: 'b' }), createTestNode({ name: 'a' }), {
-          ...compareOptions,
-          alphabet: 'c',
-        }),
-      ).toBe(0)
     })
 
     it('gives maximum priority to void', () => {
       expect(
-        compare(createTestNode({ name: 'a' }), createTestNode({ name: '' }), {
-          ...compareOptions,
-          alphabet: 'a',
+        compare({
+          options: {
+            ...options,
+            alphabet: 'a',
+          },
+          a: createTestNode({ name: 'a' }),
+          b: createTestNode({ name: '' }),
         }),
       ).toBe(1)
       expect(
-        compare(createTestNode({ name: '' }), createTestNode({ name: 'a' }), {
-          ...compareOptions,
-          alphabet: 'a',
+        compare({
+          options: {
+            ...options,
+            alphabet: 'a',
+          },
+          b: createTestNode({ name: 'a' }),
+          a: createTestNode({ name: '' }),
         }),
       ).toBe(-1)
     })
@@ -278,55 +323,105 @@ describe('compare', () => {
       locales: 'en-US' as const,
       order: 'desc' as const,
       ignoreCase: false,
+      alphabet: '',
     }
 
     it('does not sort', () => {
       expect(
-        compare(createTestNode({ name: 'b' }), createTestNode({ name: 'a' }), {
-          ...compareOptions,
+        compare({
+          a: createTestNode({ name: 'b' }),
+          b: createTestNode({ name: 'a' }),
+          options: compareOptions,
         }),
       ).toBe(0)
     })
   })
 
+  describe('"nodeValueGetter"', () => {
+    let options = {
+      specialCharacters: 'keep' as const,
+      type: 'alphabetical' as const,
+      locales: 'en-US' as const,
+      order: 'asc' as const,
+      ignoreCase: false,
+      alphabet: '',
+    }
+
+    it('sorts using the "nodeValueGetter"', () => {
+      let a = createTestNode({
+        additionalProperties: { value: 'b' },
+        name: 'a',
+      })
+      let b = createTestNode({
+        additionalProperties: { value: 'a' },
+        name: 'b',
+      })
+      expect(
+        compare({
+          options: {
+            ...options,
+            fallbackSort: { type: 'unsorted' },
+          },
+          nodeValueGetter: node =>
+            'value' in node ? (node.value as string) : '',
+          a,
+          b,
+        }),
+      ).toBe(1)
+    })
+  })
+
   describe('fallback sorting', () => {
-    let compareOptions = {
+    let options = {
       specialCharacters: 'keep' as const,
       type: 'line-length' as const,
       locales: 'en-US' as const,
       order: 'desc' as const,
       ignoreCase: false,
+      alphabet: '',
     }
 
     it('sorts using the fallback configuration', () => {
-      let nodeAaa = createTestNode({ name: 'aaa' })
-      let nodeBbb = createTestNode({ name: 'bbb' })
+      let a = createTestNode({ name: 'aaa' })
+      let b = createTestNode({ name: 'bbb' })
       expect(
-        compare(nodeBbb, nodeAaa, {
-          ...compareOptions,
-          fallbackSort: {
-            type: 'alphabetical',
-            order: 'asc',
-          } as const,
+        compare({
+          options: {
+            ...options,
+            fallbackSort: {
+              type: 'alphabetical',
+              order: 'asc',
+            },
+          },
+          a: b,
+          b: a,
         }),
       ).toBe(1)
 
       expect(
-        compare(nodeBbb, nodeAaa, {
-          ...compareOptions,
-          fallbackSort: {
-            type: 'alphabetical',
-            order: 'desc',
-          } as const,
+        compare({
+          options: {
+            ...options,
+            fallbackSort: {
+              type: 'alphabetical',
+              order: 'desc',
+            },
+          },
+          a: b,
+          b: a,
         }),
       ).toBe(-1)
 
       expect(
-        compare(nodeBbb, nodeAaa, {
-          ...compareOptions,
-          fallbackSort: {
-            type: 'alphabetical',
-          } as const,
+        compare({
+          options: {
+            ...options,
+            fallbackSort: {
+              type: 'alphabetical',
+            },
+          },
+          a: b,
+          b: a,
         }),
       ).toBe(-1)
     })
@@ -335,20 +430,31 @@ describe('compare', () => {
       let node = createTestNode({ name: 'aaa' })
       let duplicateNode = createTestNode({ name: 'aaa' })
       expect(
-        compare(node, duplicateNode, {
-          ...compareOptions,
-          fallbackSort: {
-            type: 'alphabetical',
-            order: 'asc',
-          } as const,
+        compare({
+          options: {
+            ...options,
+            fallbackSort: {
+              type: 'alphabetical',
+              order: 'asc',
+            } as const,
+          },
+          b: duplicateNode,
+          a: node,
         }),
       ).toBe(0)
     })
   })
 
-  let createTestNode = ({ name }: { name: string }): SortingNode =>
+  let createTestNode = ({
+    additionalProperties,
+    name,
+  }: {
+    additionalProperties?: object
+    name: string
+  }): SortingNode =>
     ({
       size: name.length,
       name,
+      ...additionalProperties,
     }) as SortingNode
 })
diff --git a/test/utils/get-custom-groups-compare-options.test.ts b/test/utils/get-custom-groups-compare-options.test.ts
new file mode 100644
index 0000000..82805ce
--- /dev/null
+++ b/test/utils/get-custom-groups-compare-options.test.ts
@@ -0,0 +1,120 @@
+import { describe, expect, it } from 'vitest'
+
+import type { CommonOptions } from '../../types/common-options'
+
+import { getCustomGroupsCompareOptions } from '../../utils/get-custom-groups-compare-options'
+
+describe('get-custom-groups-compare-options', () => {
+  let baseOptions: Pick<CommonOptions, 'fallbackSort' | 'order' | 'type'> = {
+    fallbackSort: {
+      type: 'unsorted',
+    },
+    type: 'alphabetical',
+    order: 'asc',
+  }
+
+  it('return the entered options if "customGroups" is not an array', () => {
+    expect(
+      getCustomGroupsCompareOptions(
+        {
+          ...baseOptions,
+          groups: ['group'],
+          customGroups: {},
+        },
+        0,
+      ),
+    ).toStrictEqual({
+      ...baseOptions,
+    })
+  })
+
+  it('return the entered options if the group is not linked to a custom group', () => {
+    expect(
+      getCustomGroupsCompareOptions(
+        {
+          ...baseOptions,
+          groups: ['group'],
+          customGroups: [],
+        },
+        0,
+      ),
+    ).toStrictEqual({
+      ...baseOptions,
+    })
+  })
+
+  it('overrides "fallbackSort"', () => {
+    expect(
+      getCustomGroupsCompareOptions(
+        {
+          ...baseOptions,
+          customGroups: [
+            {
+              fallbackSort: {
+                type: 'unsorted',
+              },
+              groupName: 'group',
+            },
+          ],
+          groups: ['group'],
+        },
+        0,
+      ),
+    ).toStrictEqual({
+      ...baseOptions,
+      fallbackSort: {
+        type: 'unsorted',
+      },
+    })
+  })
+
+  it('overrides "type"', () => {
+    expect(
+      getCustomGroupsCompareOptions(
+        {
+          ...baseOptions,
+          customGroups: [
+            {
+              groupName: 'group',
+              type: 'unsorted',
+            },
+          ],
+          groups: ['group'],
+        },
+        0,
+      ),
+    ).toStrictEqual({
+      ...baseOptions,
+
+      fallbackSort: {
+        type: 'unsorted',
+      },
+      type: 'unsorted',
+    })
+  })
+
+  it('overrides "order"', () => {
+    expect(
+      getCustomGroupsCompareOptions(
+        {
+          ...baseOptions,
+          customGroups: [
+            {
+              groupName: 'group',
+              order: 'desc',
+            },
+          ],
+          groups: ['group'],
+        },
+        0,
+      ),
+    ).toStrictEqual({
+      ...baseOptions,
+
+      fallbackSort: {
+        type: 'unsorted',
+      },
+      order: 'desc',
+    })
+  })
+})
diff --git a/test/utils/get-settings.test.ts b/test/utils/get-settings.test.ts
index f3f899f..239efa4 100644
--- a/test/utils/get-settings.test.ts
+++ b/test/utils/get-settings.test.ts
@@ -20,6 +20,7 @@ describe('get-settings', () => {
 
   it('accepts official settings provided', () => {
     let allowedOptions: { [key in keyof Required<Settings>]: Settings[key] } = {
+      fallbackSort: { type: 'alphabetical' },
       partitionByComment: 'value',
       specialCharacters: 'keep',
       partitionByNewLine: true,
diff --git a/test/utils/sort-nodes-by-groups.test.ts b/test/utils/sort-nodes-by-groups.test.ts
index 60cd488..719c3d3 100644
--- a/test/utils/sort-nodes-by-groups.test.ts
+++ b/test/utils/sort-nodes-by-groups.test.ts
@@ -1,18 +1,23 @@
 import { describe, expect, it } from 'vitest'
 
+import type { BaseSortNodesByGroupsOptions } from '../../utils/sort-nodes-by-groups'
 import type { SortingNode } from '../../types/sorting-node'
 
 import { sortNodesByGroups } from '../../utils/sort-nodes-by-groups'
 
 describe('sort-nodes-by-groups', () => {
-  let compareOptions = {
+  let options: BaseSortNodesByGroupsOptions = {
     fallbackSort: { type: 'unsorted' },
     specialCharacters: 'keep',
     type: 'alphabetical',
     ignoreCase: false,
     locales: 'en-US',
     order: 'asc',
+    alphabet: '',
   } as const
+  let getOptionsByGroupNumber: () => {
+    options: BaseSortNodesByGroupsOptions
+  } = () => ({ options })
 
   it('sorts nodes by groups', () => {
     let nodeA = createTestNode({ group: 'group2', name: 'a' })
@@ -20,9 +25,11 @@ describe('sort-nodes-by-groups', () => {
     let nodeC = createTestNode({ group: 'group2', name: 'c' })
     let nodeD = createTestNode({ group: 'group1', name: 'd' })
     expect(
-      sortNodesByGroups([nodeD, nodeC, nodeB, nodeA], {
-        ...compareOptions,
+      sortNodesByGroups({
+        nodes: [nodeD, nodeC, nodeB, nodeA],
+        ignoreEslintDisabledNodes: false,
         groups: ['group1', 'group2'],
+        getOptionsByGroupNumber,
       }),
     ).toStrictEqual([nodeB, nodeD, nodeA, nodeC])
   })
@@ -39,31 +46,23 @@ describe('sort-nodes-by-groups', () => {
 
     it('should ignore eslint disabled nodes if "ignoreEslintDisabledNodes" is true', () => {
       expect(
-        sortNodesByGroups(
-          [nodeD, nodeC, nodeB, nodeA],
-          {
-            ...compareOptions,
-            groups: ['group1', 'group2'],
-          },
-          {
-            ignoreEslintDisabledNodes: true,
-          },
-        ),
+        sortNodesByGroups({
+          nodes: [nodeD, nodeC, nodeB, nodeA],
+          ignoreEslintDisabledNodes: true,
+          groups: ['group1', 'group2'],
+          getOptionsByGroupNumber,
+        }),
       ).toStrictEqual([nodeB, nodeC, nodeD, nodeA])
     })
 
     it('should not ignore eslint disabled nodes if "ignoreEslintDisabledNodes" is false', () => {
       expect(
-        sortNodesByGroups(
-          [nodeD, nodeC, nodeB, nodeA],
-          {
-            ...compareOptions,
-            groups: ['group1', 'group2'],
-          },
-          {
-            ignoreEslintDisabledNodes: false,
-          },
-        ),
+        sortNodesByGroups({
+          nodes: [nodeD, nodeC, nodeB, nodeA],
+          ignoreEslintDisabledNodes: false,
+          groups: ['group1', 'group2'],
+          getOptionsByGroupNumber,
+        }),
       ).toStrictEqual([nodeB, nodeD, nodeA, nodeC])
     })
   })
@@ -75,17 +74,13 @@ describe('sort-nodes-by-groups', () => {
       let nodeC = createTestNode({ group: 'group2', name: 'c' })
       let nodeD = createTestNode({ group: 'group1', name: 'd' })
       expect(
-        sortNodesByGroups(
-          [nodeD, nodeC, nodeB, nodeA],
-          {
-            ...compareOptions,
-            groups: ['group1', 'group2'],
-          },
-          {
-            isNodeIgnored: node => node === nodeC,
-            ignoreEslintDisabledNodes: false,
-          },
-        ),
+        sortNodesByGroups({
+          isNodeIgnored: node => node === nodeC,
+          nodes: [nodeD, nodeC, nodeB, nodeA],
+          ignoreEslintDisabledNodes: false,
+          groups: ['group1', 'group2'],
+          getOptionsByGroupNumber,
+        }),
       ).toStrictEqual([nodeB, nodeC, nodeD, nodeA])
     })
   })
@@ -99,24 +94,49 @@ describe('sort-nodes-by-groups', () => {
       let nodeE = createTestNode({ group: 'group2', name: 'e' })
       let nodeF = createTestNode({ group: 'group1', name: 'f' })
       expect(
-        sortNodesByGroups(
-          [nodeF, nodeE, nodeD, nodeC, nodeB, nodeA],
-          {
-            ...compareOptions,
-            groups: ['group1', 'group2'],
-          },
-          {
-            isNodeIgnoredForGroup: node => node === nodeB,
-            ignoreEslintDisabledNodes: false,
-          },
-        ),
+        sortNodesByGroups({
+          nodes: [nodeF, nodeE, nodeD, nodeC, nodeB, nodeA],
+          isNodeIgnoredForGroup: node => node === nodeB,
+          ignoreEslintDisabledNodes: false,
+          groups: ['group1', 'group2'],
+          getOptionsByGroupNumber,
+        }),
       ).toStrictEqual([nodeD, nodeF, nodeB, nodeA, nodeC, nodeE])
     })
   })
 
-  let createTestNode = (node: {
-    isEslintDisabled?: boolean
-    group?: string
-    name: string
-  }): SortingNode => node as SortingNode
+  it('should handle "nodeValueGetter"', () => {
+    let nodeA = createTestNode(
+      { group: 'group1', name: 'a' },
+      { actualValue: 'b' },
+    )
+    let nodeB = createTestNode(
+      { group: 'group1', name: 'a' },
+      { actualValue: 'a' },
+    )
+    expect(
+      sortNodesByGroups({
+        getOptionsByGroupNumber: () => ({
+          nodeValueGetter: node => node.actualValue,
+          options,
+        }),
+        ignoreEslintDisabledNodes: false,
+        nodes: [nodeA, nodeB],
+        groups: ['group1'],
+      }),
+    ).toStrictEqual([nodeB, nodeA])
+  })
+
+  let createTestNode = <T extends object>(
+    node: {
+      isEslintDisabled?: boolean
+      group: string
+      name: string
+    },
+    additionalParameters?: T,
+  ): SortingNode & T =>
+    ({
+      ...node,
+      ...additionalParameters,
+    }) as SortingNode & T
 })
diff --git a/test/utils/sort-nodes.test.ts b/test/utils/sort-nodes.test.ts
index c08d7fa..ada8915 100644
--- a/test/utils/sort-nodes.test.ts
+++ b/test/utils/sort-nodes.test.ts
@@ -5,19 +5,26 @@ import type { SortingNode } from '../../types/sorting-node'
 import { sortNodes } from '../../utils/sort-nodes'
 
 describe('sort-nodes', () => {
-  let compareOptions = {
+  let options = {
     fallbackSort: { type: 'unsorted' },
     specialCharacters: 'keep',
     type: 'alphabetical',
     ignoreCase: false,
     locales: 'en-US',
     order: 'asc',
+    alphabet: '',
   } as const
 
   it('sorts nodes', () => {
     let a = createTestNode({ name: 'a' })
     let b = createTestNode({ name: 'b' })
-    expect(sortNodes([b, a], compareOptions)).toStrictEqual([a, b])
+    expect(
+      sortNodes({
+        ignoreEslintDisabledNodes: false,
+        nodes: [b, a],
+        options,
+      }),
+    ).toStrictEqual([a, b])
   })
 
   describe('ignoreEslintDisabledNodes', () => {
@@ -27,16 +34,20 @@ describe('sort-nodes', () => {
 
     it('should ignore eslint disabled nodes if "ignoreEslintDisabledNodes" is true', () => {
       expect(
-        sortNodes([nodeB, nodeC, nodeA], compareOptions, {
+        sortNodes({
           ignoreEslintDisabledNodes: true,
+          nodes: [nodeB, nodeC, nodeA],
+          options,
         }),
       ).toStrictEqual([nodeA, nodeC, nodeB])
     })
 
     it('should not ignore eslint disabled nodes if "ignoreEslintDisabledNodes" is false', () => {
       expect(
-        sortNodes([nodeB, nodeC, nodeA], compareOptions, {
+        sortNodes({
           ignoreEslintDisabledNodes: false,
+          nodes: [nodeB, nodeC, nodeA],
+          options,
         }),
       ).toStrictEqual([nodeA, nodeB, nodeC])
     })
@@ -48,16 +59,38 @@ describe('sort-nodes', () => {
       let nodeB = createTestNode({ name: 'b' })
       let nodeC = createTestNode({ name: 'c' })
       expect(
-        sortNodes([nodeB, nodeC, nodeA], compareOptions, {
+        sortNodes({
           isNodeIgnored: node => node === nodeC,
           ignoreEslintDisabledNodes: false,
+          nodes: [nodeB, nodeC, nodeA],
+          options,
         }),
       ).toStrictEqual([nodeA, nodeC, nodeB])
     })
   })
 
-  let createTestNode = (node: {
-    isEslintDisabled?: boolean
-    name: string
-  }): SortingNode => node as SortingNode
+  it('should handle "nodeValueGetter"', () => {
+    let nodeA = createTestNode({ name: 'a' }, { actualValue: 'b' })
+    let nodeB = createTestNode({ name: 'b' }, { actualValue: 'a' })
+    expect(
+      sortNodes({
+        nodeValueGetter: node => node.actualValue,
+        ignoreEslintDisabledNodes: false,
+        nodes: [nodeA, nodeB],
+        options,
+      }),
+    ).toStrictEqual([nodeB, nodeA])
+  })
+
+  let createTestNode = <T extends object>(
+    node: {
+      isEslintDisabled?: boolean
+      name: string
+    },
+    additionalParameters?: T,
+  ): SortingNode & T =>
+    ({
+      ...node,
+      ...additionalParameters,
+    }) as SortingNode & T
 })