Skip to content

Instantly share code, notes, and snippets.

@Rich-Harris
Created May 18, 2017 16:40
Show Gist options
  • Save Rich-Harris/24a8ddd3947150aa8c15a9367faf1d62 to your computer and use it in GitHub Desktop.
Save Rich-Harris/24a8ddd3947150aa8c15a9367faf1d62 to your computer and use it in GitHub Desktop.
why deopting on `import *` is bad

Most people treat these is interchangeable:

// named import
import { bar } from './foo.js';
bar();

// namespace import
import * as foo from './foo.js';
foo.bar();

Generally, the point here is that foo is a collection of functions (or other values) — it's not supposed to be thought of as an object. If the author wants bar to be a method of foo rather than a standalone function, she should write it as such and have a default export foo with a property bar. (This isn't just an aesthetic choice — the author has no control over which import form people will use. Assuming people will use the namespace form is bad programming.)

Rollup treats the two forms as equivalent (demo 1, demo 2). If it didn't, it would have to import all of foo, including the bits that aren't used. (It does deoptimise like this if there's a dynamic lookup on foo, or if foo is e.g. exported or passed to a function.) That would suck.

The only time the two forms aren't equivalent is if bar uses this. If Rollup can analyse bar and determine that that's the case, it can a) warn and b) deoptimise. (That doesn't currently happen but it could.) But if bar looked like this...

function makeAFunction () {
  return function () {
    console.log('analyse', this);
  }
}

export const bar = makeAFunction();

...then analysis gets much harder — in some cases, it would be impossible. So Rollup is faced with a choice between a) deoptimising every time it can't fully analyse a namespace import (lots of false positives, would completely defeat tree-shaking), and b) not being 100% spec-compliant in this case, where the author wrote some bad code. The ideological choice is b, the pragmatic choice is a.

@jasonkuhrt
Copy link

@ljharb Why haven't you considered the qualities of readability as a use-case for namespaced imports?

Pseudo examples

import * as React from 'react'
...
React.render
import * as JSON from 'json`

JSON.parse
import * as MyLib from 'mylib'

type settings = MyLib.Settings & { ... }

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