eslint-plugin-perfectionist: sorting imports, objects and JSX props with ESLint autofix
☂️ ESLint plugin for sorting various data such as objects, imports, types, enums, JSX props, etc.
At a glance
- What is it?
- An ESLint plugin that turns ordering into a lint rule: objects, imports, TypeScript types, enums and JSX props sorted alphabetically, naturally or by line length, with every rule auto-fixable. The interesting question is not whether it works, but whether your team wants a linter deciding where a key goes.
- Who is it for?
- Adopt it if your team already argues about import order in review and wants that argument settled by a rule rather than by a reviewer. Skip it if your ordering is semantic, if your codebase is mid-migration to another linter, or if you cannot afford a large one-time diff.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 6 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 25, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem is not formatting, it is where the argument happens
Prettier and ESLint's own formatting rules decide how a line looks. Neither decides what comes first. That gap is where review comments live: a new import lands above an existing group, a JSX prop gets appended to the end of a component, an enum member is added wherever the cursor happened to be. The README frames the value in terms of readability, maintainability and code review, and its most direct sentence is about process rather than aesthetics: if a rule says there is only one way to do something, nobody spends time deciding how to do it.
The plugin is for teams that have already accepted this trade. It is an ESLint plugin, so it inherits ESLint's configuration model, its editor integrations and its --fix pipeline. It is not a formatter and it does not touch whitespace. It reorders members inside a construct and leaves the construct's formatting to whatever else you run.
The scope is wider than imports. The README lists objects, imports, TypeScript types, enums, JSX props and Svelte attributes, and the rules table in the repository begins with sort-arrays. The package description names the same set. If your ordering complaint is limited to imports, you are installing a plugin that does considerably more than that, and you will spend configuration effort turning the rest off.
How the sorting rules actually work
Each rule targets one syntactic construct and exposes three decisions: what to compare, in which direction, and how to treat members that do not participate. The README's usage example sets type to natural and order to asc, which maps to the three sort modes the description names: alphabetical, natural, or by line length.
Alphabetical is character comparison. Natural treats embedded numbers as numbers, so item2 sorts before item10 rather than after it. Line length sorts by how long the rendered line is, and the recommended-line-length config uses descending order, which puts the longest member first. That last mode is the one worth thinking about: it optimizes for a visual shape rather than for lookup, and it will move a member when a single character in its name changes.
The plugin also ships an alphabet export. The package.json declares a subpath export at ./alphabet pointing to dist/utils/alphabet.js, so the comparison table used by the rules is reachable from your own code rather than being locked inside the rule implementations. The README does not explain what you would do with it, which is a small documentation gap rather than a functional one.
All rules are described as automatically fixable, and the rules table marks them with the wrench symbol tied to ESLint's --fix option. That is the mechanism that matters in practice: the rule reports a violation, and ESLint rewrites the file. There is no separate codemod step and no custom CLI.
Installing it and getting a first fix
The README requires ESLint v8.45.0 or greater and gives two install commands. Run them in the project where the linting happens.
npm install --save-dev eslint
npm install --save-dev eslint-plugin-perfectionistThe shortest path to a working setup is a built-in config rather than a hand-written rule list. The flat config example imports the plugin and uses one of the ready-made configs.
import perfectionist from 'eslint-plugin-perfectionist'
export default [
perfectionist.configs['recommended-natural'],
]If you are still on the deprecated .eslintrc format, the equivalent is an extends entry: plugin:perfectionist/recommended-natural-legacy.
Before letting the config loose, see what it would change. ESLint's --fix writes to disk, so run it on a branch with a clean working tree and inspect the diff.
npx eslint . --fixThe README does not state how many violations a fresh recommended config produces on an existing codebase, and no changelog entry quantifies it. Expect the first run to be large if the project has never enforced ordering, and treat that diff as the actual cost of adoption.
If you prefer one rule to the whole config, the README's usage section shows the shape: register the plugin under plugins, then configure perfectionist/sort-imports with options type and order.
rules: {
'perfectionist/sort-imports': [
'error',
{ type: 'natural', order: 'asc' },
],
}Where the plugin is the wrong tool
Ordering carries meaning in some constructs, and the plugin cannot know that. A discriminated union where the first member is the default, a set of enum values whose numeric order is load-bearing, an object literal whose keys are read positionally: sorting these changes behaviour or at least changes intent. The README's safety claim is about the fixer being mechanically correct, not about your ordering being semantically irrelevant. Those are different promises, and the second one is yours to make.
The recommended configs enable all recommended rules at once. That is convenient and also the reason first-run diffs get large: you are not adopting one rule, you are adopting the plugin's opinion about every construct it covers. Teams that want imports only should configure sort-imports alone and leave the configs alone.
There is also a class of conflict the README does not address. If another plugin or a framework convention wants a specific member first, the two rules will fight, and ESLint's --fix will apply whichever ran last. Precedence handling between conflicting rules is not documented, so this is something to discover on your own code rather than something you can read up on.
Finally, this is an ESLint plugin. If your linting runs through a different engine, the plugin is not portable to it. The question of whether a faster linter can replace ESLint is a separate decision, and adopting a plugin deepens your commitment to the ESLint ecosystem.
Compared with the import-ordering plugins people already run
eslint-plugin-import is the incumbent for import order, and the difference is scope rather than quality. It is an import resolver and linting toolkit whose ordering rule is one feature among many; perfectionist is an ordering plugin whose entire surface is sorting. If imports are your only concern and you already run eslint-plugin-import for resolution, adding perfectionist for the same job means two plugins with opinions about the same lines.
The second difference is the fixer model. eslint-plugin-import's ordering rule is fixable too, but perfectionist applies the same three sort modes and the same option vocabulary across every construct it covers, so learning sort-imports teaches you sort-objects, sort-types and the rest. That consistency is the plugin's real product.
Unicorn and SonarJS are frequently installed alongside it and occupy different ground: they flag patterns and correctness issues, not member order. There is no overlap to resolve there, and no reason to choose between them.
For the broader question of ESLint versus Biome, nothing in the plugin's documentation mentions Biome support, and the package is published as an ESLint plugin with ESLint's plugin API. Treat any assumption that it works under a different linter as unverified.
Maintenance, releases and what the MIT licence covers
The repository is not archived and the last push was on 2026-09-22, the same day as the v5.12.0 release. The two prior releases, v5.11.1 and v5.11.0, landed on 2026-09-15 and 2026-08-31. That is a steady release cadence over the past month, and the version number is at 5.x, so upgrades within the major line are the normal case.
The package is published under the MIT licence, and the repository carries a license.md at the top level. MIT is permissive: it allows use, modification and redistribution with the licence and copyright notice retained. That is a statement about the licence text, not advice about your situation; if your organisation has rules about dependency licences, the file to read is license.md in the repository.
Upgrade cost is the part the documentation does not help with. The changelog.md file exists at the top level and the repository has a changelog.config.ts, so release notes are generated, but nothing published describes breaking changes between 5.x versions or a migration path from 4.x. The practical consequence: pin the version, read changelog.md before bumping, and expect that a plugin whose output is an autofix will surface breaking changes as a large diff rather than as a runtime error.
Editorial conclusion
Adopt it if your team already argues about import order in review and wants that argument settled by a rule rather than by a reviewer. Skip it if your ordering is semantic, if your codebase is mid-migration to another linter, or if you cannot afford a large one-time diff. Before enabling anything, run the recommended config over a scratch branch and read the diff, because the plugin's own README calls the rules automatically fixable and safe, and that claim deserves your eyes on your own code rather than on a screenshot.
Frequently asked questions
What are the best ESLint plugins?
This plugin is one candidate among several that are commonly installed together. Its specific contribution is ordering: rules that sort objects, imports, TypeScript types, enums, JSX props and Svelte attributes, all of them automatically fixable.
Which linter is better, ESLint or Biome?
eslint-plugin-perfectionist is published as an ESLint plugin and uses ESLint's plugin API, so it runs wherever ESLint runs. The README and package metadata say nothing about Biome support.
What is prettier vs ESLint?
The two solve different problems, and this plugin sits on the ESLint side. It reorders members inside constructs such as objects and imports and leaves whitespace and line formatting to whatever formatter you already run.
Can Oxlint replace ESLint?
The README requires ESLint v8.45.0 or greater and the package exports an ESLint plugin entry point. Nothing in the documentation describes running the sorting rules under Oxlint.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/azat-io-eslint-plugin-perfectionist)