Search code examples
javascriptecmascript-6ecmascript-next

Scoped Exports in JS


Once we export something inJS. For instance, in a file called foo.js we have a line that says::

export default foo;

We can import it globally from any file we want. But what if there is a need to avoid it.

Here's a problem statement:

  • Consider that X is an application having modules A and B in it.
  • Each module A and B contains a file parser.js which has some exported functions with the same name.
  • Assume that A and B are independent modules.
  • If A and B are independent modules, in principle, the modules shouldn't have access to the functions/functionalities outside their scope.
  • Due to the exports being globally available, while developing, one has access to the functions in both parser.js files and he/she may unknowingly use the wrong piece of code.

Is there a way to define a scope to where exported modules can only be used up to a certain level.

If not, then are there any creative ways to go around the problem?

Looking for ideas to ease development problems/experience at scale :)


Solution

  • You can just use aliasing to avoid a naming conflict:

    import {
      foo,
    } from './some/path';
    
    import {
      foo as bar,
    } from './some/other/path';
    

    But yes, most libraries have a single entry point (typically index.js) that exports the functionality of the sub-modules, and all you have to do is not export the module you want hidden. Now certainly, someone could still import the sub-module you want hidden directly by specifying a path to it in the node_modules folder, but someone doing that is a) foolishly relying on a non-public API and b) probably playing at a high enough level to avoid that kind of mistake.

    As for application code consumed directly, just either wrap it in a library you add to package.json from e.g. a git url, or simply comment the code or change the name. Typescript can also help, if the functions have different type signatures it won't be possible to use one where you meant the other.

    But in the end, the simplest path is to just have a little faith in your fellow developers: way, way, way too much effort goes in to trying to prevent people from making mistakes they are unlikely to make.

    EDIT based on comment

    Imports can be namespaced like so:

    import * as Whatever from 'some-module';
    
    Whatever.someFn();