Skip to content

Commit 51f656f

Browse files
authored
add more docs
1 parent 9693129 commit 51f656f

File tree

1 file changed

+110
-0
lines changed

1 file changed

+110
-0
lines changed

README.md

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,113 @@ Imports that bypass an index file are discouraged, but may sometimes be necessar
7676
// in components/ComponentX/ComponentX.tsx
7777
import { helperFunc } from '../../lib/UtilityX/helper';
7878
```
79+
80+
81+
82+
83+
## Avoid Export Default - TypeScript Deep Dive
84+
85+
> [source https://basarat.gitbook.io/typescript/main-1/defaultisbad](https://basarat.gitbook.io/typescript/main-1/defaultisbad)
86+
87+
> Consider you have a file foo.ts with the following contents:
88+
89+
90+
Consider you have a file `foo.ts` with the following contents:
91+
92+
You would import it (in `bar.ts`) using ES6 syntax as follows:
93+
94+
There are a few maintainability concerns here:
95+
96+
- If you refactor `Foo` in `foo.ts` it will not rename it in `bar.ts`.
97+
98+
99+
- If you end up needing to export more stuff from `foo.ts` (which is what many of your files will have) then you have to juggle the import syntax.
100+
101+
102+
For this reason I recommend simple exports + destructured import. E.g. `foo.ts`:
103+
104+
import { Foo } from "./foo";
105+
106+
Below I also present a few more reasons.
107+
108+
### Poor Discoverability
109+
110+
Discoverability is very poor for default exports. You cannot explore a module with intellisense to see if it has a default export or not.
111+
112+
With export default you get nothing here (maybe it does export default / maybe it doesn't `¯\_(ツ)_/¯`):
113+
114+
```typescript
115+
import /\* here \*/ from 'something';
116+
```
117+
Without export default you get a nice intellisense here:
118+
119+
```typescript
120+
import { /\* here \*/ } from 'something';
121+
```
122+
123+
### Autocomplete
124+
125+
Irrespective of if you know about the exports, you even autocomplete at this `import {/*here*/} from "./foo";` cursor location. Gives your developers a bit of wrist relief.
126+
127+
### CommonJS interop
128+
129+
With `default` there is horrible experience for commonJS users who have to `const {default} = require('module/foo');` instead of `const {Foo} = require('module/foo')`. You will most likely want to rename the `default` export to something else when you import it.
130+
131+
### Typo Protection
132+
133+
You don't get typos like one dev doing `import Foo from "./foo";` and another doing `import foo from "./foo";`
134+
135+
### TypeScript auto-import
136+
137+
Auto import quickfix works better. You use `Foo` and auto import will write down `import { Foo } from "./foo";` cause its a well-defined name exported from a module. Some tools out there will try to magic read and _infer_ a name for a default export but magic is flaky.
138+
139+
### Re-exporting
140+
141+
Re-exporting is common for the root `index` file in npm packages, and forces you to name the default export manually e.g. `export { default as Foo } from "./foo";` (with default) vs. `export * from "./foo"` (with named exports).
142+
143+
### Dynamic Imports
144+
145+
Default exports expose themselves badly named as `default` in dynamic `import`s e.g.
146+
147+
```typescript
148+
const HighCharts \= await import('https://code.highcharts.com/js/es-modules/masters/highcharts.src.js');
149+
150+
HighCharts.default.chart('container', { ... }); // Notice \`.default\`
151+
```
152+
Much nicer with named exports:
153+
```typescript
154+
const {HighCharts} \= await import('https://code.highcharts.com/js/es-modules/masters/highcharts.src.js');
155+
156+
HighCharts.chart('container', { ... }); // Notice \`.default\`
157+
```
158+
159+
### Needs two lines for non-class / non-function
160+
161+
Can be one statement for function / class e.g.
162+
163+
```typescript
164+
export default function foo() {
165+
}
166+
```
167+
168+
Can be one statement for _non named / type annotated_ objects e.g.:
169+
170+
171+
```typescript
172+
export default {
173+
notAFunction: 'Yeah, I am not a function or a class',
174+
soWhat: 'The export is now *removed* from the declaration'
175+
};
176+
```
177+
178+
But needs two statements otherwise:
179+
180+
```typescript
181+
// If you need to name it (here \`foo\`) for local use OR need to annotate type (here \`Foo\`)
182+
183+
notAFunction: 'Yeah, I am not a function or a class',
184+
185+
soWhat: 'The export is now \*removed\* from the declaration'
186+
};
187+
export default foo;
188+
```

0 commit comments

Comments
 (0)