From ce540b636672854b71420c72fa00f45595aa332b Mon Sep 17 00:00:00 2001 From: Maxim Mazurok Date: Tue, 10 Aug 2021 00:06:22 +1000 Subject: [PATCH] [Fix] `ExportMap`: Add default export when esModuleInterop is true and anything is exported Fixes #2183. See #1689. --- CHANGELOG.md | 4 ++++ src/ExportMap.js | 22 ++++++++++++++----- .../index.d.ts | 19 ++++++++++++++++ .../tsconfig.json | 5 +++++ tests/src/rules/default.js | 11 ++++++++++ 5 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 tests/files/typescript-export-react-test-renderer/index.d.ts create mode 100644 tests/files/typescript-export-react-test-renderer/tsconfig.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 998055e61..d8993f0d3 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 76b07f9dc..46d3cfe88 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; }; 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 000000000..ff70c7135 --- /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): Promise; 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 000000000..a72ee3e88 --- /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 c7eb780d0..a861fff76 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,