Replace wildcard imports

JavaScript pattern

Replace wildcard imports with explicit imports.

Simple example

BEFORE
import * as foo from 'abc';

console.log(foo.nice);

console.log(foo.baz);

const king = foo.change();
AFTER
import { nice, baz, change } from 'abc';

console.log(nice);

console.log(baz);

const king = change();

Multiple cases example

BEFORE
import * as foo from 'abc';
import * as two from 'somewhere';

// * imports with no refs are kept
import * as three from 'elsewhere';

console.log(foo.nice);
two.thing();
AFTER
import { nice } from 'abc';
import { thing } from 'somewhere';

// * imports with no refs are kept
import * as three from 'elsewhere';

console.log(nice);
thing();

Avoid variable collisions

If the module identifier is already used in the program, keep the wildcard import

BEFORE
import * as foo from 'abc';

// This is an unrelated `log` wrapping the module log
const log = (msg) => {
  foo.log("nice stuff");
  foo.other();
};
log();
AFTER
import * as foo from 'abc';
import { other } from 'abc';

// This is an unrelated `log` wrapping the module log
const log = (msg) => {
  foo.log("nice stuff");
  other();
};
log();

Handle JSX

Component names should also be analyzed for identifiers.

BEFORE
import * as Foo from 'abc';
import * as Sam from 'abc';

const Component = () => {
  return (
    <Sam.King>
      <Foo.Nice />
    </Sam.King>
  );
};
AFTER
import { Nice } from 'abc';
import { King } from 'abc';

const Component = () => {
  return (
    <King>
      <Nice />
    </King>
  );
};

Avoid duplicate imports

BEFORE
import * as foo from 'abc';

foo.thing();
foo.other();
foo.thing();
AFTER
import { thing, other } from 'abc';

thing();
other();
thing();

Avoid shadowed imports

BEFORE
import * as foo from 'abc';

console.log(foo.bar);

const log = (foo) => {
  foo.log('nice stuff');
  foo.other();
};
AFTER
import { bar } from 'abc';

console.log(bar);

const log = (foo) => {
  foo.log('nice stuff');
  foo.other();
};