-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Suggestion]: import/named-order
: Enforce to sort specifiers of import, export, require
#2553
Comments
import/named-orderEnforce a convention in the order of Rule DetailsThe following patterns are valid: import { Alpha, Bravo } from 'foo' const { Alpha, Bravo } = require('foo') const Alpha = 'A'
const Bravo = 'B'
export { Alpha, Bravo } The following patterns are invalid: import { Bravo, Alpha } from 'foo' // <- reported const { Bravo, Alpha } = require('foo') // <- reported const Alpha = 'A'
const Bravo = 'B'
export { Alpha, Bravo } // <- reported Options
|
Related tslint rule: https://palantir.github.io/tslint/rules/ordered-imports Good for some dependencies like import {
BehaviorSubject,
combineLatest,
distinctUntilChanged,
map,
switchMap,
tap,
} from 'rxjs'; I don't think two options like |
Option names are weird when I look at it again. I want to control that applying or not of import, export, and require with esmodule/commonjs options. In general, it may be an unnecessary option, but I guess that it is necessary to have an option to not apply import or export or require for some environment. So I think there should be an option like below. Options
|
Any real usage case? |
I would assume ordering should apply to either/both imports and exports, configurably. I’m still not clear on the benefit here. Forced sorting doesn’t have any impact on merge conflicts, and there shouldn’t be so many different things exported by one file anyways. |
It does IMO. For instance: import {
combineLatest,
distinctUntilChanged,
map,
switchMap,
tap,
} from 'rxjs'; If two users want to add But without this rule, the two users can have different results: import {
+ BehaviorSubject,
combineLatest, vs tap,
+ BehaviorSubject,
} from 'rxjs';
That's |
I see what you mean - it doesn’t impact merge conflicts (it may even increase them) but it does prevent duplication conflicts. |
No, that’s not good for treeshaking - treeshaking can only ever be a half-assed attempt to delete unused code. The best thing for bundle size is always maximally granular deep imports, which does a much better job than treeshaking can, due to the nature of the JS language. So no, it’s not a valid or a beneficial choice, although it certainly is a choice. |
I'm not quite sure to understand why it may even increase merge conflicts by consistently sorting?
import {
combineLatest,
distinctUntilChanged,
map,
switchMap,
tap,
} from 'rxjs'; vs import { combineLatest } from 'rxjs/operators/combineLatest'
import { distinctUntilChanged } from 'rxjs/operators/distinctUntilChanged'
import { map } from 'rxjs/operators/map'
import { switchMap } from 'rxjs/operators/switchMap'
import { tap } from 'rxjs/operators/tap' I'd prefer the first one. 😂 (Although this is not the key point for this rule here.) |
When importing an external library, I think it is a good direction to import it separately for tree shaking. However, tree shaking is often unnecessary in internal code. In my case, there are more than 20 specifiers of import and If this is not aligned, it will decrease readability (it cannot be shared because it is an internal code of my company 😢 ). I looked for a similar example.. import type {
EndpointDefinitions,
EndpointBuilder,
EndpointDefinition,
ReplaceTagTypes,
} from './endpointDefinitions' In the above case, it seems to be well aligned, but the |
@JounQin it increases merge conflicts because you can’t add items at arbitrary locations, so any changes to anything that’s an alphabetical neighbor will conflict with your change. As for the two options, the second is objectively superior even if you think it’s aesthetically worse, and aesthetics is much less important than bundle size/memory footprint as well as conceptual cleanliness. |
@ronparkdev treeshaking is only ever necessary when you import from a file that exports more than you need, internal or otherwise. Why are all 20 of those types coming from the same file? |
@ljharb It's an off-the-topic part of this discussion, It seems that a lot of interfaces or types are imported when the data model is deep and the business logic is complex in the typescript environment. |
@JounQin I thought about it, but it seems unnecessary to provide as options. Even if there are some code in which the rule should not be used, it is likely to use |
@ronparkdev I don't think it's off topic - if it's indeed a bad practice to have so many named imports (such that ordering is required), then there's no benefit in making a rule to deal with a case you shouldn't be experiencing in the first place. |
You can't convince all library authors to agree with this statement. And which practice is better depends on the authors' and end users' preferences, IMO. import {
combineLatest,
distinctUntilChanged,
map,
switchMap,
tap,
} from 'rxjs'; This is how |
That's totally fair that I can't convince every library author not to do something bad. CJS only has default exports, so it seems like the |
|
@ljharb, I totally agree a case that using a lot of named imports is a bad practice. But, many developers try to match the order of named import, but they can not match it perfectly every times. That's why I thought of this rule to use in this case. Like the case below, the number of named imports is a few but, maybe they need help from this rule. AS-ISimport type {
EndpointDefinitions,
EndpointBuilder,
EndpointDefinition,
ReplaceTagTypes,
} from './endpointDefinitions' TO-BEimport type {
EndpointDefinition, // <- relocated
EndpointDefinitions,
EndpointBuilder,
ReplaceTagTypes,
} from './endpointDefinitions' But, to be honest, I think there are more developers who don't care about this strict order. So, It is ambiguous to be included in the recommended config. But, I think some of the developers feel it's necessary? |
Great stuff @ronparkdev, would love to have this rule 🙇♂️ 🚀 |
A useful rule, in my opinion. In addition, it would be nice if it also touches on " import { type B, a, b, type A } from "some-module"
import { a, b, type A, type B } from "some-module" // Change the above to this |
Such a rule would also help with find+replace across a codebase since each import of items would assume a canonical form. // find+replace on `import { Alpha, Bravo } from 'module';` misses the b.js reference
// file a.js
import { Alpha, Bravo } from 'module';
// file b.js
import { Bravo, Alpha } from 'module'; |
I just prepared a Pull Request for this feature as I skimmed through the comments and will also add support for specifying whether or not checking the ordering of ESModule imports/exports and CommonJS imports separately (i.e. something like Stay tuned and stuff! |
Sorry, It was my first time posting a PR, so I didn't know that I had to create an issue first.
I experienced a significant decrease in readability as the number of specifiers increased in the named import. So, I made this rule.
I already add a rule to PR #2552
The text was updated successfully, but these errors were encountered: