Skip to content

Rule proposal: no-rename-default #1041

@steve-taylor

Description

@steve-taylor

Consider the following:

components/foo.js:

export default class Foo extends React.Component {
    render() {
        // ...
    }
}

widgets/foo.js:

import FooComponent from '../components/foo';

export default class Foo extends BaseWidget {
    constructor() {
        super(FooComponent);
    }

    // ...
}

Foo (in components/foo.js) and FooComponent are exactly the same thing, but have been renamed via default import/export. When one thing has two or more names, it increases the difficulty of comprehending code, especially when there are many functions, classes, etc. that are renamed on import.

The proposal is to have a rule that generates a warning or error when a default import is given a different name than a default export.

Activity

ljharb

ljharb commented on Mar 12, 2018

@ljharb
Member

This is a valuable part of both default and named import syntax (the ability to rename things), and I’m not sure why it’s an issue that needs a rule.

steve-taylor

steve-taylor commented on Mar 12, 2018

@steve-taylor
Author

It’s an issue for the reasons outlined above. There are already plenty of rules that, when applied, restrict the usage of language capabilities that some people may find useful. It’s a matter of preference.

ljharb

ljharb commented on Mar 12, 2018

@ljharb
Member

What would happen when you wanted to use the Foo component and widget in the same file?

Separately, i think that it’s not at all apparent that it’s more difficult to comprehend code when something has a different name in different files; the point of a module is that you think about one module (file) at a time.

steve-taylor

steve-taylor commented on Mar 12, 2018

@steve-taylor
Author

What would happen when you wanted to use the Foo component and widget in the same file?

At that point, I'd consider naming things more appropriately. For example, I'd look at adopting a naming convention whereby widgets are suffixed by Widget (e.g. FooWidget).

As a last resort, there's always // eslint-disable-line: import/no-rename-default, but it's unlikely to be used when a naming convention is in place.

steve-taylor

steve-taylor commented on Mar 12, 2018

@steve-taylor
Author

Let's also consider the following case (and I've been guilty of this before):

export default function getDefaultFoo() {
    // ....
}
import getMainFoo from '../foos/normal';

This can come about as my understanding of the scope, purpose and/or context of a function/class evolves while building it and using it for the first time. It would be nice to have a linting rule to remind me to clean this up by enforcing uniformity between its declared name and its imported name.

For those who don't see this as an issue, they can simply choose not to use this rule, like any other stylistic rule.

steve-taylor

steve-taylor commented on Mar 12, 2018

@steve-taylor
Author

the point of a module is that you think about one module (file) at a time.

It would be nice if feature tickets and modules were nicely aligned. In reality (team of 5+ devs working on the same rapidly evolving codebase), implementing a feature typically involves reading, comprehending, and even modifying numerous modules. Hopefully you can appreciate that this proposal has come about based on a real dev team pain point rather than a contrived stylistic need.

ljharb

ljharb commented on Mar 13, 2018

@ljharb
Member

It's also important to note that a default export need not have a name at all, consider export default () => {} or export default class { } - what would your rule do in that case?

Effectively this rule would disable a major feature of the language, the ability to rename imports (you're only requesting the default, but presumably it could apply to named as well via an option).

Perhaps you could share more about the pain points you hope to solve?

steve-taylor

steve-taylor commented on Mar 13, 2018

@steve-taylor
Author

Effectively this rule would disable a major feature of the language

These rules also disable major features of the language:

  • import/no-anonymous-default-export - cannot export default () => {}, for example
  • no-default-export - no export default at all
  • import/no-unassigned-import - disables polyfills

Will they be removed?

what would your rule do in that case?

Ignore these exports. Use it with import/no-anonymous-default-export to ensure that never happens.

ljharb

ljharb commented on Mar 13, 2018

@ljharb
Member

@steve-taylor fair point on existing rules that do that.

Can you explain more about the pain points? "it increases the difficulty of comprehending code" isn't something I've seen, on very large codebases, so I'd love something a bit more concrete to motivate this rule.

steve-taylor

steve-taylor commented on Mar 13, 2018

@steve-taylor
Author

You’re smarter than me, then! The issue is that when there are a number of similarly named functions with a similar purpose that return the same type of object, but they are inconsistently named in default exports vs imports, it makes it more difficult than it needs to be to build a mental model of complex code. Same goes for classes. When one function or class has two names, it’s unnecessary noise, which is never a good thing when you’re reading code.

It’s hard to provide a less abstract example without handing over my employer’s code.

If you’re trying to figure out whether the effort is justified, I can save you most of the effort by submitting a pull request.

ljharb

ljharb commented on Mar 14, 2018

@ljharb
Member

The effort I'm concerned about is future maintenance, not just the actual PR :-) Certainly it would be awesome if you were able to submit a PR if the request becomes accepted.

The readability issues you're talking about only apply when multiple of these similarly-named items are used in the same file? If so, wouldn't renames, in that file, actually help understand what the code is doing?

steve-taylor

steve-taylor commented on Mar 14, 2018

@steve-taylor
Author

Not the same file. Spread throughout the same project.

ljharb

ljharb commented on Mar 14, 2018

@ljharb
Member

I'm confused; when do you need a mental model beyond the file you're currently looking at, and its direct dependencies?

23 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Participants

      @ljharb@omasback@FlorianWendelborn@steve-taylor@threehams

      Issue actions

        Rule proposal: no-rename-default · Issue #1041 · import-js/eslint-plugin-import