Perfectionist

sort-imports

Enforce sorted imports.

Maintaining a consistent and sorted order of imports is crucial for improving code readability and organization.

This rule ensures that imports are easily locatable and quickly scannable, especially in modules with numerous import statements.

By reducing the likelihood of errors caused by import conflicts and providing a clear structure, this rule helps developers manage imports efficiently and maintain a tidy codebase.

Important

If you use the sort-imports rule or the order rule from the eslint-plugin-import plugin, it is highly recommended to disable them to avoid conflicts.

If you use the prettier-plugin-sort-imports plugin, remove them from the prettier config to avoid conflicts.

Rule perfectionist/sort-imports works in a similar way to rule import/order, but with some differences:

  1. Supporting for new import types:
  • 'side-effect'
  • 'style'
  • 'builtin-type'
  • 'internal-type'
  • 'parent-type'
  • 'sibling-type'
  • 'index-type'
  1. Supporting for adding custom import groups
  2. Sorting not only alphabetically, but also naturally and by line length

Try it out

Options

This rule accepts an options object with the following properties:

type

default: 'alphabetical'

Specifies the sorting method.

  • 'alphabetical' — Sort items alphabetically (e.g., “a” < “b” < “c”) using localeCompare.
  • 'natural' — Sort items in a natural order (e.g., “item2” < “item10”).
  • 'line-length' — Sort items by the length of the code line (shorter lines first).

order

default: 'asc'

Determines whether the sorted items should be in ascending or descending order.

  • 'asc' — Sort items in ascending order (A to Z, 1 to 9).
  • 'desc' — Sort items in descending order (Z to A, 9 to 1).

ignoreCase

default: true

Controls whether sorting should be case-sensitive or not.

  • true — Ignore case when sorting alphabetically or naturally (e.g., “A” and “a” are the same).
  • false — Consider case when sorting (e.g., “a” comes before “A”).

specialCharacters

default: keep

Controls whether special characters should be trimmed, removed or kept before sorting.

  • 'keep' — Keep special characters when sorting (e.g., “_a” comes before “a”).
  • 'trim' — Trim special characters when sorting alphabetically or naturally (e.g., “_a” and “a” are the same).
  • 'remove' — Remove special characters when sorting (e.g., “/a/b” and “ab” are the same).

locales

default: 'en-US'

Specifies the sorting locales. See String.prototype.localeCompare() - locales.

  • string — A BCP 47 language tag (e.g. 'en', 'en-US', 'zh-CN').
  • string[] — An array of BCP 47 language tags.

internalPattern

default: ['^~/.*']

Allows you to specify a pattern for identifying internal imports. This is useful for distinguishing your own modules from external dependencies.

You can use regexp patterns to define these internal imports.

sortSideEffects

default: false

Specifies whether side effect imports should be sorted. By default, sorting side-effect imports is disabled for security reasons.

  • true — Sort side effect imports.
  • false — Do not sort side effect imports.

partitionByComment

default: false

Allows you to use comments to separate imports into logical groups.

  • true — All comments will be treated as delimiters, creating partitions.
  • false — Comments will not be used as delimiters.
  • string — A regexp pattern to specify which comments should act as delimiters.
  • string[] — An array of regexp patterns to specify which comments should act as delimiters.

partitionByNewLine

default: false

When true, the rule will not sort imports if there is an empty line between them. This can be useful for keeping logically separated groups of members in their defined order.

import { b1, b2 } from 'b'

import { a } from 'a'
import { c } from 'c'

newlinesBetween

default: 'always'

Specifies how new lines should be handled between import groups.

  • ignore — Do not report errors related to new lines between import groups.
  • always — Enforce one new line between each group, and forbid new lines inside a group.
  • never — No new lines are allowed in the entire import section.

This options is only applicable when partitionByNewLine is false.

maxLineLength

default: undefined

Specifies a maximum line length for sorting imports. When the line length exceeds this number, sorting will be based only on the import name, excluding the elements.

This option is only available when the type is set to 'line-length'.

tsconfigRootDir

default: undefined

Specifies the directory of the root tsconfig.json file (ex: .). This is used for marking aliased imports as internal or internal-type in the groups option.

groups

type: Array<string | string[]>

default:

[
  'type',
  ['builtin', 'external'],
  'internal-type',
  'internal',
  ['parent-type', 'sibling-type', 'index-type'],
  ['parent', 'sibling', 'index'],
  'object',
  'unknown',
]

Allows you to specify a list of import groups for sorting. Groups help organize imports into meaningful categories, making your code more readable and maintainable.

Predefined groups:

  • 'builtin' — Node.js Built-in Modules.
  • 'external' — External modules installed in the project.
  • 'internal' — Your internal modules.
  • 'parent' — Modules from the parent directory.
  • 'sibling' — Modules from the same directory.
  • 'side-effect' — Side effect imports.
  • 'side-effect-style' — Side effect style imports.
  • 'index' — Main file from the current directory.
  • 'object' — TypeScript object imports.
  • 'style' — Styles.
  • 'external-type' — TypeScript type imports from external modules.
  • 'builtin-type' — TypeScript type imports from built-in modules.
  • 'internal-type' — TypeScript type imports from your internal modules.
  • 'parent-type' — TypeScript type imports from the parent directory.
  • 'sibling-type' — TypeScript type imports from the same directory.
  • 'index-type' — TypeScript type imports from the main directory file.
  • 'unknown' — Imports that don’t fit into any group specified in the groups option.

If the unknown group is not specified in the groups option, it will automatically be added to the end of the list.

Each import will be assigned a single group specified in the groups option (or the unknown group if no match is found). The order of items in the groups option determines how groups are ordered.

Within a given group, members will be sorted according to the type, order, ignoreCase, etc. options.

Individual groups can be combined together by placing them in an array. The order of groups in that array does not matter. All members of the groups in the array will be sorted together as if they were part of a single group.

Example

// 'builtin' - Node.js Built-in Modules
import path from 'path'
// 'external' - External modules installed in the project
import axios from 'axios'
// 'internal' - Your internal modules
import Button from '~/components/Button'
// 'parent' - Modules from parent directory
import formatNumber from '../utils/format-number'
// 'sibling' - Modules from the same directory
import config from './config'
// 'side-effect' - Side effect imports
import './set-production-env.js'
// side-effect-style - Side effect style imports
import './styles.scss'
// 'index' - Main file from the current directory
import main from '.'
// 'object' - TypeScript object-imports
import log = console.log
// 'style' - Styles
import styles from './index.module.css'
// 'external-type' - TypeScript type imports
import type { FC } from 'react'
// 'builtin-type' - TypeScript type imports from Built-in Modules
import type { Server } from 'http'
// 'internal-type' - TypeScript type imports from your internal modules
import type { User } from '~/users'
// 'parent-type' - TypeScript type imports from parent directory
import type { InputProps } from '../Input'
// 'sibling-type' - TypeScript type imports from the same directory
import type { Details } from './data'
// 'index-type' - TypeScript type imports from main directory file
import type { BaseOptions } from './index.d.ts'

customGroups

type:

{
  value: { [groupName: string]: string | string[] }
  type: { [groupName: string]: string | string[] }
}
default: { value: {}, type: {} }

You can define your own groups and use regexp pattern to match specific imports.

Each key of the value or type fields represents a group name which you can then use in the groups option. The value for each key can either be of type:

  • string — An import matching the value will be marked as part of the group referenced by the key.
  • string[] — An import matching any of the values of the array will be marked as part of the group referenced by the key. The order of values in the array does not matter.

Custom group matching takes precedence over predefined group matching.

Example

   groups: [
+    'react',
     'type',
     ['builtin', 'external'],
+    'lodash',
     'internal-type',
     'internal',
     ['parent-type', 'sibling-type', 'index-type'],
     ['parent', 'sibling', 'index'],
     'object',
     'unknown',
   ],
+  customGroups: {                      
+    value: {                           
+     react: ['^react$', '^react-.+'],
+     lodash: 'lodash',
+    },
+    type: {                            
+      react: ['^react$', '^react-.+'],
+    }                                  
+  },
 }

environment

default: 'node'

Specifies which environment’s built-in modules should be recognized. If you are using Bun, change the value to 'bun'.

Usage

Version

This rule was introduced in v0.9.0.

Resources

Table of Contents