noRestrictedImports
Diagnostic Category: lint/nursery/noRestrictedImports
Since: v1.6.0
Sources:
- Same as:
no-restricted-imports
- Same as:
@typescript-eslint/no-restricted-imports
Description
Section titled DescriptionDisallow specified modules when loaded by import or require.
Examples
Section titled Examples{ "noRestrictedImports": { "options": { "paths": { "lodash": "Using lodash is not encouraged", "underscore": "Using underscore is not encouraged" } } }}
Since: v2
{ "options": { "paths": { "lodash": "Using lodash is not encouraged.", "underscore": "", "import-foo": { "importNames": ["Bar"] }, "import-bar": { "allowImportNames": ["Bar"] } } }}
Invalid
Section titled Invalidimport "lodash";import "allowed-import";
code-block.js:1:8 lint/nursery/noRestrictedImports ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⚠ Using lodash is not encouraged.
> 1 │ import “lodash”;
│ ^^^^^^^^
2 │ import “allowed-import”;
3 │
const underscore = await import("underscore");
code-block.js:1:33 lint/nursery/noRestrictedImports ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⚠ Do not import ‘underscore’.
> 1 │ const underscore = await import(“underscore”);
│ ^^^^^^^^^^^^
2 │
const lodash = require("lodash");
code-block.js:1:24 lint/nursery/noRestrictedImports ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⚠ Using lodash is not encouraged.
> 1 │ const lodash = require(“lodash”);
│ ^^^^^^^^
2 │
Valid
Section titled Validimport "allowed-import";const myImport = await import("allowed-import");const myImport = require("allowed-import");
Supported Import Syntaxes
Section titled Supported Import SyntaxesThe rule tries to parse the context of the import to see if only one or more of the allowed import names have been imported from a given module.
All of the following import syntaxes are supported:
Static import
(and re-export
) declarations
Section titled Static import (and re-export) declarationsNormal static ESM import
declarations are supported:
// Static `import` declaration:// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
import "sideeffect-import";import * as alias1 from "namespace-import";import { export1, export2 as alias2, "string-name" as alias3, default as defaultExport /* … */ } from "named-import";import defaultExport from "default-import";import defaultExport, * as alias5 from "default+namespace-import";import defaultExport, { export1 /* … */ } from "default+named-import";
export * from "namespace-import";export { export1, export2 as alias2, "string-name" as alias3, default as defaultExport /* … */ } from "named-import";
The TypeScript-specific type-only imports are also supported:
// TypeScript-specific type-only `import` declaration:// https://www.typescriptlang.org/docs/handbook/modules/reference.html#type-only-imports-and-exports
import { type export1, type export2 as alias2, type "string-name" as alias3, type default as defaultExport /* … */ } from "named-import";import type { export1, export2 as alias2, "string-name" as alias3, default as defaultExport /* … */ } from "named-import";import type defaultExport from "default-import";
Dynamic import()
calls
Section titled Dynamic import() callsDynamic ESM import()
calls are also supported.
Because the import is performed at runtime, it is not always possible to determine which import names are being used.
Nevertheless, the rule tries to detect the following common usage patterns where the set of imported names is determined statically:
// Dynamic `import()` calls:// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import
import('sideeffect-import');await import('sideeffect-import');
// ...using await + destructuring-assignment:const alias1 = await import('namespace-import');const { default: defaultExport } = await import('default-import')const { export1, export2: alias2, "string-name": alias3, default: defaultExport /* … */ } = await import("named-import");
// ...using then() with arrow-function + destructuring parameters:import('namespace-import').then(alias1 => { /* … */ });import('namespace-import').then((alias1) => { /* … */ });import('default-import').then(({ default: defaultExport }) => { /* … */ });import('named-import').then(({ export1, export2: alias2, "string-name": alias3, default: defaultExport /* … */ }) => { /* … */ });
// ...using then() with function + destructuring parameters:import('namespace-import').then(function(alias1) { /* … */ });import('default-import').then(function({ default: defaultExport }) { /* … */ });import('named-import').then(function({ export1, export2: alias2, "string-name": alias3, default: defaultExport /* … */ }) { /* … */ });
// Standalone `import('...')` calls that appear in some other// unrecognized context will be treated as a namespace import,// because the return value of `import('...')` is a namespace object:
myFunction(...args, import("namespace-import"), ...args)
Dynamic require()
calls
Section titled Dynamic require() callsNodeJS-style require()
calls are also supported.
Due to the way require()
works, these are always treated as default imports.
// Dynamic `require()` callconst defaultExport = require('default-import');
Options
Section titled Options{ "noRestrictedImports": { "options": { "paths": { "lodash": "Using lodash is not encouraged", "underscore": "Using underscore is not encouraged" } } }}
Since: v2
Use the options to specify the import paths and/or specific import names within them that you want to restrict in your source code.
{ "options": { "paths": { "lodash": "Using lodash is not encouraged", "underscore": "Using underscore is not encouraged", "import-foo": { "importNames": ["Bar"], "message": "Please use Bar from /import-bar/baz/ instead." }, "import-bar": { "allowImportNames": ["Bar"], "message": "Please use only Bar from import-bar." } } }}
paths
Section titled pathsAn object that lists the import paths that are either wholly or partially restricted.
The keys of the object are the import paths to restrict, and the values can be:
- A string with a custom message to show in the diagnostic when any
- An object with additional options, as explained below.
In the example below, we restrict the two paths services-deprecated
and constants
, with two particular messages.
Importing services-deprecated
will emit the message Use services instead.
.
Importing constants
will emit the message This file will be deleted soon.
:
{ "options": { "paths": { "services-deprecated": { "message": "Use services instead." }, "constants": "This file will be deleted soon." } }}
import * as namespaceAlias from 'services-deprecated';
code-block.js:1:33 lint/nursery/noRestrictedImports ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⚠ Use services instead.
> 1 │ import * as namespaceAlias from ‘services-deprecated’;
│ ^^^^^^^^^^^^^^^^^^^^^
2 │
import { export1 } from 'constants';
code-block.js:1:25 lint/nursery/noRestrictedImports ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⚠ This file will be deleted soon.
> 1 │ import { export1 } from ‘constants’;
│ ^^^^^^^^^^^
2 │
paths.<import>.message
Section titled paths.<import>.messageSpecifies the message to be shown when the restricted import is used.
A default message will be generated if message
is empty or not specified:
{ "options": { "paths": { "import-foo": { } } }}
import { export1 } 'import-foo';
code-block.js:1:20 parse ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✖ expected from
but instead found 'import-foo'
> 1 │ import { export1 } ‘import-foo’;
│ ^^^^^^^^^^^^
2 │
ℹ Remove ‘import-foo’
paths.<import>.importNames
Section titled paths.<import>.importNamesSpecifies the array of import names that should be explicitly forbidden. The following import name specifiers are supported:
- Named import:
"someIdentifier"
(import { someIdentifier } from 'named-import'
) - Default import:
"default"
(import defaultExport from 'default-import'
) - Namespace import:
"*"
(import * as alias1 from 'namespace-import'
) - Side effect/Bare import:
""
(import "sideeffect-import"
)
Only one of importNames
and allowImportNames
must be specified.
{ "options": { "paths": { "import-foo": { "importNames": ["Bar"], "message": "Please use Bar from /import-bar/baz/ instead." } } }}
Invalid
Section titled Invalidimport { Bar } from 'import-foo';
code-block.js:1:10 lint/nursery/noRestrictedImports ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⚠ Please use Bar from /import-bar/baz/ instead.
> 1 │ import { Bar } from ‘import-foo’;
│ ^^^
2 │
Valid
Section titled Validimport { Foo } from 'import-foo';
paths.<import>.allowImportNames
Section titled paths.<import>.allowImportNamesSpecifies the set of import names that should be explicitly allowed.
See importNames
for the set of supported import name specifiers.
Only one of importNames
and allowImportNames
must be specified.
{ "options": { "paths": { "import-bar": { "allowImportNames": ["Bar"] } } }}
Invalid
Section titled Invalidimport { Baz } from 'import-bar';
code-block.js:1:10 lint/nursery/noRestrictedImports ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⚠ Do not import ‘Baz’ from ‘import-bar’.
> 1 │ import { Baz } from ‘import-bar’;
│ ^^^
2 │
ℹ Only the following imports from ‘import-bar’ are allowed:
- Bar
Valid
Section titled Validimport { Bar } from 'import-bar';
How to configure
Section titled How to configure{ "linter": { "rules": { "nursery": { "noRestrictedImports": "error" } } }}