https://github.com/typeofweb/proposal-qualified-imports
https://github.com/typeofweb/proposal-qualified-imports
Last synced: about 2 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/typeofweb/proposal-qualified-imports
- Owner: typeofweb
- License: mit
- Created: 2022-02-11T13:14:08.000Z (about 4 years ago)
- Default Branch: main
- Last Pushed: 2023-07-21T22:54:00.000Z (over 2 years ago)
- Last Synced: 2025-06-11T06:03:50.939Z (9 months ago)
- Homepage: https://mmiszy.github.io/proposal-qualified-imports/
- Size: 124 KB
- Stars: 15
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Qualified Imports ECMAScript Proposal
**Author**: Michał Miszczyszyn (@mmiszy)
## Summary
Introduce new syntax that allows for creating an object from imports:
```js
import { a, b, fn } as Package from './package.js';
```
## Motivation
When using ECMAScript modules, it's often desired to import only certain named exports like so:
```js
import { a, b, fn } from "./package.js";
```
This is currently part of the ECMAScript specification and is widely supported. However, some problems arise when using multiple imports in the same file.
### Vague names
It's often the case that small utility functions with vague names are being exported from modules, and they only make sense when put in a certain context. For instance:
```js
import { fmap } from "./functor.js";
```
```js
import { fmap } from "./applicative.js";
```
```js
import { fmap } from "./monad.js";
```
Out of context, `fmap` could be either of those implementations.
### Name conflicts
Importing two (or more) named exports from different packages results in a conflict of declarations:
```js
import { a } from "./one.js";
import { a } from "./two.js"; // Error!
```
This can be currently solved by renaming the imports:
```js
import { a as aOne } from "./one.js";
import { a as aTwo } from "./two.js";
```
Yet, it quickly becomes cumbersome when we have multiple imports such as when using utility libraries:
```js
import {
map as lodashMap,
reduce as lodashReduce,
find as lodashFind,
filter as lodashFilter,
// … etc.
} from "./lodash.js";
import {
map as bluebirdMap,
reduce as bluebirdReduce,
find as bluebirdFind,
filter as bluebirdFilter,
// … etc.
} from "./bluebird.js";
```
## Proposed Solution
Qualified Imports: a new syntax that allows importing multiple named exports and grouping them into a namespace. Compare:
### Vague names solution
```js
import { fmap } as Functor from "./functor.js";
Functor.fmap(/* … */);
```
```js
import { fmap } as Applicative from "./applicative.js";
Applicative.fmap(/* … */);
```
```js
import { fmap } as Monad from "./monad.js";
Monad.fmap(/* … */);
```
### Name conflicts solution
```js
import {
map,
reduce,
find,
filter,
// … etc.
} as Lodash from "./lodash.js";
import {
map,
reduce,
find,
filter,
// … etc.
} as Bluebird from "./bluebird.js";
Lodash.find(/* … */);
Bluebird.map(/* … */);
```
## FAQ
### Why not just use `import * as X from './x.js'` ?
Even though this might work for certain scenarios, it makes it more difficult to reason about the modules being used. This is a problem not only for the developers due to the lack of readability but also for the tooling which might not be able to correctly determine whether particular exports are used or not.
Moreover, there's an overhead related to parsing and gathering all of the exports in a single namespace – compared to just a few we might want to use.
## Previous work
### Haskell
Haskell has rich syntax for imports and qualified imports:
```hs
import qualified Data.List (sort, fold, map)
Data.List.sort …
Data.List.fold …
Data.List.map …
```
Alternatively, imports can be grouped and renamed:
```hs
import qualified Data.Map.Lazy (lookup) as Map
```
> Supposing that the module `Mod` exports four functions named `x`, `y`, `z`, and `(+++)`:
| Import command | What is brought into scope | Notes |
| ----------------------------------- | ------------------------------------------------ | -------------------------------------------------------------------------- |
| `import Mod` | `x, y, z, (+++), Mod.x, Mod.y, Mod.z, (Mod.+++)` | (By default, qualified and unqualified names.) |
| `import Mod ()` | (Nothing!) | (Useful for only importing instances of typeclasses and nothing else) |
| `import Mod (x,y, (+++))` | `x, y, (+++), Mod.x, Mod.y, (Mod.+++)` | (Only `x`, `y`, and `(+++)`, no `z`.) |
| `import qualified Mod` | `Mod.x, Mod.y, Mod.z, (Mod.+++)` | (Only qualified versions; no unqualified versions.) |
| `import qualified Mod (x,y)` | `Mod.x, Mod.y` | (Only `x` and `y`, only qualified.) |
| `import Mod hiding (x,y,(+++))` | `z, Mod.z` | (`x` and `y` are hidden.) |
| `import qualified Mod hiding (x,y)` | `Mod.z, (Mod.+++)` | (`x` and `y` are hidden.) |
| `import Mod as Foo` | `x, y, z, (+++), Foo.x, Foo.y, Foo.z, (Foo.+++)` | (Unqualified names as before. Qualified names use `Foo` instead of `Mod`.) |
| `import Mod as Foo (x,y)` | `x, y, Foo.x, Foo.y` | (Only import `x` and `y`.) |
| `import qualified Mod as Foo` | `Foo.x, Foo.y, Foo.z, (Foo.+++)` | (Only qualified names, using new qualifier.) |
| `import qualified Mod as Foo (x,y)` | `Foo.x, Foo.y` | (Only qualified versions of `x` and `y`, using new qualifier) |
source: https://wiki.haskell.org/Import
### Purescript
Modules in Purescript can be qualified and they allow for selective imports:
```purescript
import Data.List (sort, fold, map) as List
```
### C#
C# supports namespaces and exports of namespaces. Such namespaces can be imported later on like so:
```cs
using Sorter = Data.List.Sorter;
```
### OCaml / ReasonML / ReScript
OCaml et al. support local opens, which are somewhat similar to qualified imports because they allow for importing a module and using it locally without polluting the global scope. For instance:
```ml
(** OCaml *)
let _ =
let open Log in
make ()
|> (logStr ("Hello"))
|> (logStr ("everyone"))
|> print
```
```re
// ReasonML / ReScript
let _ = Log.(
make()
|> logStr("Hello")
|> logStr("everyone")
|> print
);
```
## Further reading
- [Similar proposal for Swift](https://gist.github.com/CodaFi/42e5e5e94d857547abc381d9a9d0afd6)