Repository: import-js/eslint-plugin-import (js)

Issue:
[import/default] - false negative for react-test-renderer
I'm doing this:
```
import reactTestRenderer from 'react-test-renderer';
```

Getting this:
```
No default export found in imported module "react-test-renderer". eslint (import/default)
```

Using these types: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/react-test-renderer/index.d.ts

And I have `esModuleInterop` in my tsconfig, so this should not throw error (thanks to https://github.com/import-js/eslint-plugin-import/pull/1689)

Pull request:
[Fix] ExportMap: Add default export when esModuleInterop is true and anything is exported
This PR aims to fix #2183 by adding default export if anything is exported and `esModuleInterop` is set to true.

This probably should've been done in #1689 that I originally opened to add `esModuleInterop` support.


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 998055e6..d8993f0d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -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
@@ -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
diff --git a/src/ExportMap.js b/src/ExportMap.js
index 76b07f9d..46d3cfe8 100644
--- a/src/ExportMap.js
+++ b/src/ExportMap.js
@@ -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 {
@@ -576,8 +577,6 @@ ExportMap.parse = function (path, content, context) {
       });
     }
 
-    const isEsModuleInteropTrue = isEsModuleInterop();
-
     const exports = ['TSExportAssignment'];
     if (isEsModuleInteropTrue) {
       exports.push('TSNamespaceExportDeclaration');
@@ -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') {
@@ -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(
@@ -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;
 };
 


Test patch:
diff --git a/tests/files/typescript-export-react-test-renderer/index.d.ts b/tests/files/typescript-export-react-test-renderer/index.d.ts
new file mode 100644
index 00000000..ff70c713
--- /dev/null
+++ b/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>;
diff --git a/tests/files/typescript-export-react-test-renderer/tsconfig.json b/tests/files/typescript-export-react-test-renderer/tsconfig.json
new file mode 100644
index 00000000..a72ee3e8
--- /dev/null
+++ b/tests/files/typescript-export-react-test-renderer/tsconfig.json
@@ -0,0 +1,5 @@
+{
+    "compilerOptions": {
+        "esModuleInterop": true
+    }
+}
diff --git a/tests/src/rules/default.js b/tests/src/rules/default.js
index c7eb780d..a861fff7 100644
--- a/tests/src/rules/default.js
+++ b/tests/src/rules/default.js
@@ -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,