Skip to content

Commit f81eabc

Browse files
snitin315nzakasmdjermanovic
authored
feat: support TS syntax in no-restricted-imports (#19562)
* feat: support TS syntax in `no-restricted-imports` * fix: update test cases * docs: add typescript options * chore: fix lint * test: add more * refactor: simplify code * test: cover more cases for exports * docs: udpate description * fix: cover more cases * fix: remove unused code * chore: fix formatting * fix: cover more cases * fix: handle more cases * fix: handle more cases * fix: correct false positives * docs: add more examples * chore: fix formatting * docs: apply suggestions from code review Co-authored-by: Nicholas C. Zakas <nicholas@humanwhocodes.com> * docs: udpate description * chore: fix formatting * docs: update examples * fix: correct false positives * refactor: code & types * refactor: types * test: add more cases * refactor: apply suggestions from code review Co-authored-by: Milos Djermanovic <milos.djermanovic@gmail.com> * test: cover more cases * refactor: code * fix: resolve comments * chore: fix lint * chore: fix formatting --------- Co-authored-by: Nicholas C. Zakas <nicholas@humanwhocodes.com> Co-authored-by: Milos Djermanovic <milos.djermanovic@gmail.com>
1 parent e1ac05e commit f81eabc

4 files changed

Lines changed: 1652 additions & 4 deletions

File tree

docs/src/rules/no-restricted-imports.md

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,61 @@ import { AllowedObject } from "foo";
282282

283283
:::
284284

285+
#### allowTypeImports (TypeScript only)
286+
287+
Whether to allow [Type-Only Imports](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export) for a path. This includes type-only `export` statements, as they are equivalent to re-exporting an `import`. Default: `false`.
288+
289+
Examples of **incorrect** code for `allowTypeImports` in `paths`:
290+
291+
::: incorrect { "sourceType": "module" }
292+
293+
```ts
294+
/*eslint no-restricted-imports: ["error", { paths: [{
295+
name: "import-foo",
296+
allowTypeImports: true,
297+
message: "Please use only type-only imports from 'import-foo'."
298+
}]}]*/
299+
300+
import foo from 'import-foo';
301+
export { Foo } from 'import-foo';
302+
```
303+
304+
:::
305+
306+
Examples of **correct** code for `allowTypeImports` in `paths`:
307+
308+
::: correct { "sourceType": "module" }
309+
310+
```ts
311+
/*eslint no-restricted-imports: ["error", { paths: [{
312+
name: "import-foo",
313+
allowTypeImports: true,
314+
message: "Please use only type-only imports from 'import-foo'."
315+
}]}]*/
316+
317+
import type foo from 'import-foo';
318+
export type { Foo } from 'import-foo';
319+
320+
import type foo = require("import-foo");
321+
```
322+
323+
:::
324+
325+
::: correct { "sourceType": "module" }
326+
327+
```ts
328+
/*eslint no-restricted-imports: ["error", { paths: [{
329+
name: "import-foo",
330+
importNames: ["Baz"],
331+
allowTypeImports: true,
332+
message: "Please use 'Baz' from 'import-foo' as a type only."
333+
}]}]*/
334+
335+
import { Bar, type Baz } from "import-foo";
336+
```
337+
338+
:::
339+
285340
### patterns
286341

287342
This is also an object option whose value is an array. This option allows you to specify multiple modules to restrict using `gitignore`-style patterns or regular expressions.
@@ -773,6 +828,119 @@ import { isEmpty } from 'utils/collection-utils';
773828

774829
:::
775830

831+
#### allowTypeImports (TypeScript only)
832+
833+
Whether to allow [Type-Only Imports](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-8.html#type-only-imports-and-export) for a path. This includes type-only `export` statements, as they are equivalent to re-exporting an `import`. Default: `false`.
834+
835+
```json
836+
"no-restricted-imports": ["error", {
837+
"patterns": [{
838+
"group": ["import/private/*"],
839+
"allowTypeImports": true,
840+
}]
841+
}]
842+
```
843+
844+
Examples of **incorrect** code for `allowTypeImports` in `patterns`:
845+
846+
::: incorrect { "sourceType": "module" }
847+
848+
```ts
849+
/*eslint no-restricted-imports: ["error", { patterns: [{
850+
group: ["import/private/*"],
851+
allowTypeImports: true,
852+
message: "Please use only type-only imports from 'import/private/*'."
853+
}]}]*/
854+
855+
import { foo } from 'import/private/bar';
856+
export { foo } from 'import/private/bar';
857+
```
858+
859+
:::
860+
861+
Examples of **correct** code for `allowTypeImports` in `patterns`:
862+
863+
::: correct { "sourceType": "module" }
864+
865+
```ts
866+
/*eslint no-restricted-imports: ["error", { patterns: [{
867+
group: ["import/private/*"],
868+
allowTypeImports: true,
869+
message: "Please use only type-only imports from 'import/private/*'."
870+
}]}]*/
871+
872+
import type { foo } from 'import/private/bar';
873+
export type { foo } from 'import/private/bar';
874+
875+
import type foo = require("import/private/bar");
876+
```
877+
878+
:::
879+
880+
::: correct { "sourceType": "module" }
881+
882+
```ts
883+
/*eslint no-restricted-imports: ["error", { patterns: [{
884+
group: ["import/private/*"],
885+
importNames: ["Baz"],
886+
allowTypeImports: true,
887+
message: "Please use 'Baz' from 'import/private/*' as a type only."
888+
}]}]*/
889+
890+
import { Bar, type Baz } from "import/private/bar";
891+
```
892+
893+
:::
894+
895+
## Known Limitations
896+
897+
TypeScript [`import = require()` syntax](https://www.typescriptlang.org/docs/handbook/2/modules.html#es-module-syntax-with-commonjs-behavior) is valid and the rule can recognize and lint such instances, but with certain limitations.
898+
899+
You can only fully restrict these imports, you cannot restrict them based on specific import names like `importNames`, `allowImportNames`, `importNamePattern`, or `allowImportNamePattern` options.
900+
901+
Examples of **incorrect** code for TypeScript import equals declarations:
902+
903+
::: incorrect { "sourceType": "module" }
904+
905+
```ts
906+
/*eslint no-restricted-imports: ["error", "disallowed-import"]*/
907+
908+
import foo = require("disallowed-import");
909+
```
910+
911+
:::
912+
913+
::: incorrect { "sourceType": "module" }
914+
915+
```ts
916+
/*eslint no-restricted-imports: ["error", {
917+
"paths": [{ "name": "disallowed-import" }]
918+
}]*/
919+
920+
import foo = require("disallowed-import");
921+
```
922+
923+
:::
924+
925+
**Note:** Import name restrictions do not apply to TypeScript import equals declarations. The following configuration will not restrict the import equals declaration:
926+
927+
::: correct { "sourceType": "module" }
928+
929+
```ts
930+
/*eslint no-restricted-imports: ["error", {
931+
"paths": [{
932+
"name": "foo",
933+
"importNames": ["foo"]
934+
}]
935+
}]*/
936+
937+
// This import equals declaration will NOT be restricted
938+
// even though it imports the entire module
939+
import foo = require("foo");
940+
```
941+
942+
:::
943+
776944
## When Not To Use It
777945

778946
Don't use this rule or don't include a module in the list for this rule if you want to be able to import a module in your project without an ESLint error or warning.

0 commit comments

Comments
 (0)