Avoid "export default"

Avoid using export default as much as possible, for reasons as:

There are a few maintainability concerns as “Rename or Other functionality”

Lets suppose we have foo.ts like

class Foo {}
export default Foo

Then you will import in bar.ts

import Foo from './foo'

If you rename your class to FoorBar as below

class FooBar {}
export default FooBar

So bar.ts will still look the same

import Foo from './foo'

Or when you export another function lets say generateFooBar, then in your bar.ts you will have to do a bit of this things: For Best-Case-Scenario just this:

import Foo, { generateFooBar } from './foo'

Otherwise:

import Foo from './foo'

const generator = Foo.generateFooBar()

Which is an overhead to deal with.

So better to have the solution without default

export class Foo {
}
...
import { Foo } from "./foo";

Discoverability is very poor for default exports

If you write in your import as i do, since i do not remember all the functions, utilities export a line like this:

import {} from './foo'

And try intellisense which every IDE has, good luck with that. Same for autocomplete

With default there is horrible experience for commonJS

Or if you work with commonJS which is one of the hypes right now you will have to write

const { default } = require('module/foo')

How nice is that?

You don’t get typos like one dev doing

I can import the exported default with many ways, vote for the right solution from provide solutions as below:

import Foo from './foo'

or

import fooDeBar from './foo'

or

import foo from './foo'

etc

Do you get the point?

Auto import quickfix works better

If you use autoimport with default, some IDE with do some tricky stuff which does not end always in correct automport. Cool, now we have to check also this step.

Re-exporting is common for the root index file in npm packages, and forces you to name the default export manually

Lets suppose that we want to do a package, and in our index.ts we should do the following trick to process with right behaviour of exporting defaults:

export { default as Foo } from './foo'

Not nice, ee? Instead if i do not have default export i can just do:

export * from './foo'

Which work better in your opinion?

Default exports expose themselves badly named as default in dynamic import

We had a use case when writing test for logger package, and we had to do this line of code:

const logger = await import('./logger')

Now to access the functionality of logger we then should do the following just to log a message:

logger.default.log('Something')

Instead without default export would have been something like:

const { log } = await import('./logger')
log('Something')

All things above ensures that all imports follow a uniform pattern

All the import would have the same approach, uniform and easy to remind.

import { Foo } from "./foo";
import { Bar } from "./bar";
...

Keep pushing forward and savor every step of your coding journey.