diff --git a/CHANGELOG.md b/CHANGELOG.md index 66d466537..58bfe0ab3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ This change log adheres to standards from [Keep a CHANGELOG](https://keepachange - [`no-unresolved`], [`extensions`]: ignore type only exports ([#2436], thanks [@Lukas-Kullmann]) - `ExportMap`: add missing param to function ([#2589], thanks [@Fdawgs]) - [`no-unused-modules`]: `checkPkgFieldObject` filters boolean fields from checks ([#2598], thanks [@mpint]) +- [`no-cycle`]: accept Flow `typeof` imports, just like `type` ([#2608], thanks [@gnprice]) ### Changed - [Tests] [`named`]: Run all TypeScript test ([#2427], thanks [@ProdigySim]) @@ -1025,6 +1026,7 @@ for info on changes for earlier releases. [`memo-parser`]: ./memo-parser/README.md +[#2608]: https://github.com/import-js/eslint-plugin-import/pull/2608 [#2605]: https://github.com/import-js/eslint-plugin-import/pull/2605 [#2602]: https://github.com/import-js/eslint-plugin-import/pull/2602 [#2598]: https://github.com/import-js/eslint-plugin-import/pull/2598 @@ -1626,6 +1628,7 @@ for info on changes for earlier releases. [@gavriguy]: https://github.com/gavriguy [@georeith]: https://github.com/georeith [@giodamelio]: https://github.com/giodamelio +[@gnprice]: https://github.com/gnprice [@golergka]: https://github.com/golergka [@golopot]: https://github.com/golopot [@GoodForOneFare]: https://github.com/GoodForOneFare diff --git a/docs/rules/no-cycle.md b/docs/rules/no-cycle.md index 1593842df..6635ba73f 100644 --- a/docs/rules/no-cycle.md +++ b/docs/rules/no-cycle.md @@ -22,6 +22,8 @@ import { b } from './dep-b.js' // reported: Dependency cycle detected. This rule does _not_ detect imports that resolve directly to the linted module; for that, see [`no-self-import`]. +This rule ignores type-only imports in Flow and TypeScript syntax (`import type` and `import typeof`), which have no runtime effect. + ## Rule Details diff --git a/src/ExportMap.js b/src/ExportMap.js index a39434bc9..d95fdb7a7 100644 --- a/src/ExportMap.js +++ b/src/ExportMap.js @@ -502,8 +502,8 @@ ExportMap.parse = function (path, content, context) { } function captureDependencyWithSpecifiers(n) { - // import type { Foo } (TS and Flow) - const declarationIsType = n.importKind === 'type'; + // import type { Foo } (TS and Flow); import typeof { Foo } (Flow) + const declarationIsType = n.importKind === 'type' || n.importKind === 'typeof'; // import './foo' or import {} from './foo' (both 0 specifiers) is a side effect and // shouldn't be considered to be just importing types let specifiersOnlyImportingTypes = n.specifiers.length > 0; @@ -515,8 +515,9 @@ ExportMap.parse = function (path, content, context) { importedSpecifiers.add(specifier.type); } - // import { type Foo } (Flow) - specifiersOnlyImportingTypes = specifiersOnlyImportingTypes && specifier.importKind === 'type'; + // import { type Foo } (Flow); import { typeof Foo } (Flow) + specifiersOnlyImportingTypes = specifiersOnlyImportingTypes + && (specifier.importKind === 'type' || specifier.importKind === 'typeof'); }); captureDependency(n, declarationIsType || specifiersOnlyImportingTypes, importedSpecifiers); } diff --git a/tests/files/cycles/flow-typeof.js b/tests/files/cycles/flow-typeof.js new file mode 100644 index 000000000..7c63f9ab7 --- /dev/null +++ b/tests/files/cycles/flow-typeof.js @@ -0,0 +1,4 @@ +// @flow +import typeof Foo from './depth-zero'; +import { typeof Bar } from './depth-zero'; +import typeof { Bar } from './depth-zero'; diff --git a/tests/src/rules/no-cycle.js b/tests/src/rules/no-cycle.js index de0083f56..155f257b7 100644 --- a/tests/src/rules/no-cycle.js +++ b/tests/src/rules/no-cycle.js @@ -111,6 +111,10 @@ ruleTester.run('no-cycle', rule, { code: 'import { bar } from "./flow-types-only-importing-multiple-types"', parser: parsers.BABEL_OLD, }), + test({ + code: 'import { bar } from "./flow-typeof"', + parser: parsers.BABEL_OLD, + }), ), invalid: [].concat(