Skip to content

⬅️ Back to Table of Contents

📄 no-restricted-imports

📊 Analysis Summary

Metric Count
🔧 Functions 11
📦 Imports 14
📊 Variables & Constants 5
📑 Type Aliases 2

📚 Table of Contents

🛠️ File Location:

📂 packages/eslint-plugin/src/rules/no-restricted-imports.ts

📤 Default Export

export default createRule<Options, MessageIds>({ ... })
Property Value
name 'no-restricted-imports'
meta.type 'suggestion'
meta.deprecated.deprecatedSince '8.64.0'
meta.deprecated.replacedBy [ { rule: { name: 'no-restricted-imports', url: 'https://eslint.org/docs/latest/rules/no-restricted-imports', }, }, ]
meta.deprecated.url 'https://github.com/typescript-eslint/typescript-eslint/pull/12527'
meta.docs.description 'Disallow specified modules when loaded by import'
meta.docs.extendsBaseRule true
meta.fixable baseRule.meta.fixable
meta.messages baseRule.meta.messages
defaultOptions []

Entry point: create — documented under Functions.


📦 Imports

Name Source
TSESTree @typescript-eslint/utils
JSONSchema4AnyOfSchema @typescript-eslint/utils/json-schema
JSONSchema4ArraySchema @typescript-eslint/utils/json-schema
JSONSchema4ObjectSchema @typescript-eslint/utils/json-schema
ArrayOfStringOrObject eslint/lib/rules/no-restricted-imports
ArrayOfStringOrObjectPatterns eslint/lib/rules/no-restricted-imports
RuleListener eslint/lib/rules/no-restricted-imports
Ignore ignore
AST_NODE_TYPES @typescript-eslint/utils
ignore ignore
InferMessageIdsTypeFromRule ../util
InferOptionsTypeFromRule ../util
createRule ../util
getESLintCoreRule ../util/getESLintCoreRule

Variables & Constants

Name Type Kind Value Exported
baseSchema { anyOf: [unknown, { items: [{ proper... const baseRule.meta.schema as { anyOf: [ unknown, { items: [ { properties: { paths:...
allowTypeImportsOptionSchema JSONSchema4ObjectSchema['properties'] const { allowTypeImports: { type: 'boolean', description: 'Whether to allow type-on...
arrayOfStringsOrObjects JSONSchema4ArraySchema const { type: 'array', items: { anyOf: [ { type: 'string' }, { type: 'object', addi...
arrayOfStringsOrObjectPatterns JSONSchema4AnyOfSchema const { anyOf: [ { type: 'array', items: { type: 'string', }, uniqueItems: true, },...
schema JSONSchema4AnyOfSchema const { anyOf: [ arrayOfStringsOrObjects, { type: 'array', additionalItems: false, ...

Functions

create(context: any): { ExportAllDeclaration?: undefined; 'ExportNamedDeclaration…

Parameters:

  • context any

Returns: { ExportAllDeclaration?: undefined; 'ExportNamedDeclaration[source]'?: undefined; ImportDeclaration?: undefined; TSImportEqualsDeclaration?: undefined; } | { ExportAllDeclaration: any; 'ExportNamedDeclaration[source]'(node: { source: NonNullable<TSESTree.ExportNamedDeclaration["source"]>; } & TSESTree.ExportNamedDeclaration): void; ImportDeclaration: (node: TSESTree.ImportDeclaration) => void; TSImportEqualsDeclaration(node: TSESTree.TSImportEqualsDeclaration): void; }

Calls:

  • baseRule.create
  • shouldCreateRule
  • getRestrictedPaths
  • allowedTypeImportPathNameSet.add
  • allowedTypeImportPathNameSet.has
  • getRestrictedPatterns
  • allowedImportTypeMatchers.push
  • ignore({ allowRelativePaths: true, ignoreCase: !restrictedPattern.caseSensitive, }).add
  • allowedImportTypeRegexMatchers.push
  • allowedImportTypeMatchers.some
  • matcher.ignores
  • allowedImportTypeRegexMatchers.some
  • regex.test
  • node.specifiers.every
  • node.source.value.trim
  • isAllowedTypeImportPath
  • isAllowedTypeImportPattern
  • rules.ImportDeclaration
  • rules.ExportNamedDeclaration
  • checkImportNode

Internal Comments:

// Following how ignore is configured in the base rule
// As long as there's one matching pattern that allows type import (x4)
// @ts-expect-error -- parent types are incompatible but it's fine for the purposes of this extension (x2)

Code
create(context) {
    const rules = baseRule.create(context);
    const { options } = context;

    if (!shouldCreateRule(rules, options)) {
      return {};
    }

    const restrictedPaths = getRestrictedPaths(options);
    const allowedTypeImportPathNameSet = new Set<string>();
    for (const restrictedPath of restrictedPaths) {
      if (
        typeof restrictedPath === 'object' &&
        restrictedPath.allowTypeImports
      ) {
        allowedTypeImportPathNameSet.add(restrictedPath.name);
      }
    }
    function isAllowedTypeImportPath(importSource: string): boolean {
      return allowedTypeImportPathNameSet.has(importSource);
    }

    const restrictedPatterns = getRestrictedPatterns(options);
    const allowedImportTypeMatchers: Ignore[] = [];
    const allowedImportTypeRegexMatchers: RegExp[] = [];
    for (const restrictedPattern of restrictedPatterns) {
      if (
        typeof restrictedPattern === 'object' &&
        restrictedPattern.allowTypeImports
      ) {
        // Following how ignore is configured in the base rule
        if (restrictedPattern.group) {
          allowedImportTypeMatchers.push(
            ignore({
              allowRelativePaths: true,
              ignoreCase: !restrictedPattern.caseSensitive,
            }).add(restrictedPattern.group),
          );
        }
        if (restrictedPattern.regex) {
          allowedImportTypeRegexMatchers.push(
            new RegExp(
              restrictedPattern.regex,
              restrictedPattern.caseSensitive ? 'u' : 'iu',
            ),
          );
        }
      }
    }
    function isAllowedTypeImportPattern(importSource: string): boolean {
      return (
        // As long as there's one matching pattern that allows type import
        allowedImportTypeMatchers.some(matcher =>
          matcher.ignores(importSource),
        ) ||
        allowedImportTypeRegexMatchers.some(regex => regex.test(importSource))
      );
    }

    function checkImportNode(node: TSESTree.ImportDeclaration): void {
      if (
        node.importKind === 'type' ||
        (node.specifiers.length > 0 &&
          node.specifiers.every(
            specifier =>
              specifier.type === AST_NODE_TYPES.ImportSpecifier &&
              specifier.importKind === 'type',
          ))
      ) {
        const importSource = node.source.value.trim();
        if (
          !isAllowedTypeImportPath(importSource) &&
          !isAllowedTypeImportPattern(importSource)
        ) {
          return rules.ImportDeclaration(node);
        }
      } else {
        return rules.ImportDeclaration(node);
      }
    }

    return {
      ExportAllDeclaration: rules.ExportAllDeclaration,
      'ExportNamedDeclaration[source]'(
        node: {
          source: NonNullable<TSESTree.ExportNamedDeclaration['source']>;
        } & TSESTree.ExportNamedDeclaration,
      ): void {
        if (
          node.exportKind === 'type' ||
          (node.specifiers.length > 0 &&
            node.specifiers.every(specifier => specifier.exportKind === 'type'))
        ) {
          const importSource = node.source.value.trim();
          if (
            !isAllowedTypeImportPath(importSource) &&
            !isAllowedTypeImportPattern(importSource)
          ) {
            return rules.ExportNamedDeclaration(node);
          }
        } else {
          return rules.ExportNamedDeclaration(node);
        }
      },
      ImportDeclaration: checkImportNode,
      TSImportEqualsDeclaration(
        node: TSESTree.TSImportEqualsDeclaration,
      ): void {
        if (
          node.moduleReference.type === AST_NODE_TYPES.TSExternalModuleReference
        ) {
          const synthesizedImport: TSESTree.ImportDeclaration = {
            ...node,
            type: AST_NODE_TYPES.ImportDeclaration,
            assertions: [],
            attributes: [],
            source: node.moduleReference.expression,
            specifiers: [
              {
                ...node.id,
                type: AST_NODE_TYPES.ImportDefaultSpecifier,
                local: node.id,
                // @ts-expect-error -- parent types are incompatible but it's fine for the purposes of this extension
                parent: node.id.parent,
              },
            ],
          };
          return checkImportNode(synthesizedImport);
        }
      },
    };
  }

tryAccess(getter: () => T, fallback: T): T

Parameters:

  • getter () => T
  • fallback T

Returns: T

Calls:

  • getter
Code
<T>(getter: () => T, fallback: T): T => {
  try {
    return getter();
  } catch {
    return fallback;
  }
}

isObjectOfPaths(obj: unknown): obj is { paths: ArrayOfStringOrObject }

Parameters:

  • obj unknown

Returns: obj is { paths: ArrayOfStringOrObject }

Calls:

  • Object.hasOwn
Code
function isObjectOfPaths(
  obj: unknown,
): obj is { paths: ArrayOfStringOrObject } {
  return !!obj && Object.hasOwn(obj, 'paths');
}

isObjectOfPatterns(obj: unknown): obj is { patterns: ArrayOfStringOrObjectPatterns }

Parameters:

  • obj unknown

Returns: obj is { patterns: ArrayOfStringOrObjectPatterns }

Calls:

  • Object.hasOwn
Code
function isObjectOfPatterns(
  obj: unknown,
): obj is { patterns: ArrayOfStringOrObjectPatterns } {
  return !!obj && Object.hasOwn(obj, 'patterns');
}

isOptionsArrayOfStringOrObject(options: Options): options is ArrayOfStringOrObject

Parameters:

  • options Options

Returns: options is ArrayOfStringOrObject

Calls:

  • isObjectOfPaths
  • isObjectOfPatterns
Code
function isOptionsArrayOfStringOrObject(
  options: Options,
): options is ArrayOfStringOrObject {
  if (isObjectOfPaths(options[0])) {
    return false;
  }
  if (isObjectOfPatterns(options[0])) {
    return false;
  }
  return true;
}

getRestrictedPaths(options: Options): ArrayOfStringOrObject

Parameters:

  • options Options

Returns: ArrayOfStringOrObject

Calls:

  • isOptionsArrayOfStringOrObject
  • isObjectOfPaths
Code
function getRestrictedPaths(options: Options): ArrayOfStringOrObject {
  if (isOptionsArrayOfStringOrObject(options)) {
    return options;
  }
  if (isObjectOfPaths(options[0])) {
    return options[0].paths;
  }
  return [];
}

getRestrictedPatterns(options: Options): ArrayOfStringOrObjectPatterns

Parameters:

  • options Options

Returns: ArrayOfStringOrObjectPatterns

Calls:

  • isObjectOfPatterns
Code
function getRestrictedPatterns(
  options: Options,
): ArrayOfStringOrObjectPatterns {
  if (isObjectOfPatterns(options[0])) {
    return options[0].patterns;
  }
  return [];
}

shouldCreateRule(baseRules: RuleListener, options: Options): baseRules is Exclude<RuleListener, Record<string, never>>

Parameters:

  • baseRules RuleListener
  • options Options

Returns: baseRules is Exclude<RuleListener, Record<string, never>>

Calls:

  • Object.keys
  • isOptionsArrayOfStringOrObject
Code
function shouldCreateRule(
  baseRules: RuleListener,
  options: Options,
): baseRules is Exclude<RuleListener, Record<string, never>> {
  if (Object.keys(baseRules).length === 0 || options.length === 0) {
    return false;
  }

  if (!isOptionsArrayOfStringOrObject(options)) {
    return !!(options[0].paths?.length || options[0].patterns?.length);
  }

  return true;
}

Internal helpers

Declared inside another function in this file.

isAllowedTypeImportPath(importSource: string): boolean

Parameters:

  • importSource string

Returns: boolean

Calls:

  • allowedTypeImportPathNameSet.has
Code
function isAllowedTypeImportPath(importSource: string): boolean {
      return allowedTypeImportPathNameSet.has(importSource);
    }

isAllowedTypeImportPattern(importSource: string): boolean

Parameters:

  • importSource string

Returns: boolean

Calls:

  • allowedImportTypeMatchers.some
  • matcher.ignores
  • allowedImportTypeRegexMatchers.some
  • regex.test

Internal Comments:

// As long as there's one matching pattern that allows type import (x4)

Code
function isAllowedTypeImportPattern(importSource: string): boolean {
      return (
        // As long as there's one matching pattern that allows type import
        allowedImportTypeMatchers.some(matcher =>
          matcher.ignores(importSource),
        ) ||
        allowedImportTypeRegexMatchers.some(regex => regex.test(importSource))
      );
    }

checkImportNode(node: TSESTree.ImportDeclaration): void

Parameters:

  • node TSESTree.ImportDeclaration

Returns: void

Calls:

  • node.specifiers.every
  • node.source.value.trim
  • isAllowedTypeImportPath
  • isAllowedTypeImportPattern
  • rules.ImportDeclaration
Code
function checkImportNode(node: TSESTree.ImportDeclaration): void {
      if (
        node.importKind === 'type' ||
        (node.specifiers.length > 0 &&
          node.specifiers.every(
            specifier =>
              specifier.type === AST_NODE_TYPES.ImportSpecifier &&
              specifier.importKind === 'type',
          ))
      ) {
        const importSource = node.source.value.trim();
        if (
          !isAllowedTypeImportPath(importSource) &&
          !isAllowedTypeImportPattern(importSource)
        ) {
          return rules.ImportDeclaration(node);
        }
      } else {
        return rules.ImportDeclaration(node);
      }
    }

Type Aliases

Options

type Options = InferOptionsTypeFromRule<typeof baseRule>;

MessageIds

type MessageIds = InferMessageIdsTypeFromRule<typeof baseRule>;

Generated by Syntax Scribe