Skip to content

Commit

Permalink
[Fix] ExportMap: Add default export when esModuleInterop is true an…
Browse files Browse the repository at this point in the history
…d anything is exported

Fixes #2183. See #1689.
  • Loading branch information
Maxim-Mazurok authored and ljharb committed Aug 9, 2021
1 parent 202e5e0 commit ce540b6
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 6 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Expand Up @@ -6,6 +6,9 @@ This change log adheres to standards from [Keep a CHANGELOG](http://keepachangel

## [Unreleased]

### Fixe
- `ExportMap`: Add default export when esModuleInterop is true and anything is exported ([#2184], thanks [@Maxim-Mazurok])

## [2.24.0] - 2021-08-08

### Added
Expand Down Expand Up @@ -822,6 +825,7 @@ for info on changes for earlier releases.

[`memo-parser`]: ./memo-parser/README.md

[#2184]: https://github.com/import-js/eslint-plugin-import/pull/2184
[#2179]: https://github.com/import-js/eslint-plugin-import/pull/2179
[#2160]: https://github.com/import-js/eslint-plugin-import/pull/2160
[#2158]: https://github.com/import-js/eslint-plugin-import/pull/2158
Expand Down
22 changes: 16 additions & 6 deletions src/ExportMap.js
Expand Up @@ -351,6 +351,7 @@ ExportMap.for = function (context) {

ExportMap.parse = function (path, content, context) {
const m = new ExportMap(path);
const isEsModuleInteropTrue = isEsModuleInterop();

let ast;
try {
Expand Down Expand Up @@ -576,8 +577,6 @@ ExportMap.parse = function (path, content, context) {
});
}

const isEsModuleInteropTrue = isEsModuleInterop();

const exports = ['TSExportAssignment'];
if (isEsModuleInteropTrue) {
exports.push('TSNamespaceExportDeclaration');
Expand Down Expand Up @@ -606,8 +605,11 @@ ExportMap.parse = function (path, content, context) {
m.namespace.set('default', captureDoc(source, docStyleParsers, n));
return;
}
if (isEsModuleInteropTrue) {
m.namespace.set('default', {});
if (
isEsModuleInteropTrue // esModuleInterop is on in tsconfig
&& !m.namespace.has('default') // and default isn't added already
) {
m.namespace.set('default', {}); // add default export
}
exportedDecls.forEach((decl) => {
if (decl.type === 'TSModuleDeclaration') {
Expand All @@ -627,8 +629,8 @@ ExportMap.parse = function (path, content, context) {
namespaceDecl.declarations.forEach((d) =>
recursivePatternCapture(d.id, (id) => m.namespace.set(
id.name,
captureDoc(source, docStyleParsers, decl, namespaceDecl, moduleBlockNode)
))
captureDoc(source, docStyleParsers, decl, namespaceDecl, moduleBlockNode),
)),
);
} else {
m.namespace.set(
Expand All @@ -645,6 +647,14 @@ ExportMap.parse = function (path, content, context) {
}
});

if (
isEsModuleInteropTrue // esModuleInterop is on in tsconfig
&& m.namespace.size > 0 // anything is exported
&& !m.namespace.has('default') // and default isn't added already
) {
m.namespace.set('default', {}); // add default export
}

return m;
};

Expand Down
19 changes: 19 additions & 0 deletions tests/files/typescript-export-react-test-renderer/index.d.ts
@@ -0,0 +1,19 @@
// case from @types/react-test-renderer

export {};

export interface ReactTestRendererJSON {
type: string;
props: { [propName: string]: any };
children: null | ReactTestRendererNode[];
}
export type ReactTestRendererNode = ReactTestRendererJSON | string;
export interface ReactTestRendererTree extends ReactTestRendererJSON {
nodeType: 'component' | 'host';
instance: any;
rendered: null | ReactTestRendererTree | ReactTestRendererTree[];
}

export function create(nextElement: any, options?: any): any;

export function act(callback: () => Promise<any>): Promise<undefined>;
@@ -0,0 +1,5 @@
{
"compilerOptions": {
"esModuleInterop": true
}
}
11 changes: 11 additions & 0 deletions tests/src/rules/default.js
Expand Up @@ -220,6 +220,17 @@ context('TypeScript', function () {
tsconfigRootDir: path.resolve(__dirname, '../../files/typescript-export-as-default-namespace/'),
},
}),
test({
code: `import Foo from "./typescript-export-react-test-renderer"`,
parser: parser,
settings: {
'import/parsers': { [parser]: ['.ts'] },
'import/resolver': { 'eslint-import-resolver-typescript': true },
},
parserOptions: {
tsconfigRootDir: path.resolve(__dirname, '../../files/typescript-export-react-test-renderer/'),
},
}),
test({
code: `import foobar from "./typescript-export-assign-property"`,
parser: parser,
Expand Down

0 comments on commit ce540b6

Please sign in to comment.