Prevent Imports From Being Used With ESLint

ESLint is a versatile tool that comes with almost 300 different rules for you to work with and enforce style guides and best practices. Among many others, it has multiple rules for restricting the use of certain expressions, which especially comes useful if you are migrating your codebase and you want to incrementally get rid of a library.

For example, to prevent certain imports in your codebase with ESLint, you can use the no-restricted-imports rule, with the following syntax:

"no-restricted-imports": ["error", "lodash", "react"]
.eslintrc
Copied to clipboard!

This will prevent two modules: lodash, and react to be imported.

Preventing imports that match a pattern

The no-restircited-imports rule can also be configured to match patterns or throw hand-crafted error messages using a configuration object:

// Restrict importing based on pattern matching:
"no-restricted-imports": ["error", {
    "paths": ["react", "lodash"],
    "patterns": ["react/*", "lodash/map/*"]
}]

// Restrict importing with a specified error message:
"no-restricted-imports": ["error", {
    "name": "lodash",
    "message": "Please remove imports from 'lodash' before commiting."
}]
.eslintrc
Copied to clipboard!

Based on the paths property, you can pass along a patterns array with the same amount of items specifying a pattern for the import you want to restrict. Here you can use glob patterns. We also have the option to use an object instead and specify the name of the import inside a name property, and the error message we want to throw inside the message property.

Learn React with Udemy

Preventing Any Syntax

Not only imports can be restricted, however. ESLint also provides a flexible option to restrict the use of any code, be it a function call or any other expression with the use of the no-restricted-syntax rule. For example, to disallow function expressions, you can add the following rule to your eslintrc file:

{
    "rules": {
        "no-restricted-syntax": ["error", "FunctionExpression"]
    }
}
.eslintrc
Copied to clipboard!

A custom error message can also be included if we pass a configuration object instead with a selector and message properties:

rules: {
    "no-restricted-syntax": [
        "error",
        {
            selector: "ImportDeclaration[source.value=/lodash/]",
            message: "Please remove the import from lodash.",
        }
    ]
}
.eslintrc
Copied to clipboard!

As you can see, we can achieve the same behavior we had with no-restricted-imports, only this time, we manually specify the selector. This works by using AST selectors. If you are unfamiliar with how AST works, I recommend checking out the tutorial below:

How to Add Extra Functionality to Your Modules With Babel

Forbid the Use of Specific Functions

If you already know how the AST works, we can use it to our advantage to use it in conjunction with the no-restricted-syntax rule, and basically prevent the use of any kind of code in your codebase. Let’s say you are migrating over to React from jQuery, and you want to prevent the use of jQuery function calls, so you can incrementally get rid of it with each new commit.

We can achieve this by adding a new no-restricted-syntax rule with the following custom selector:

rules: {
    "no-restricted-syntax": [
      "warn",
      {
        selector: "CallExpression[callee.name=$]",
        message: "jQuery functions are deprecated. Please use React instead.",
      }
    ],
  },
.eslintrc
Copied to clipboard!

So what is going on here? Let’s break it down. First and foremost, we want the rule to be a warning instead of an error, otherwise, we would need to refactor the whole codebase at once. For the selector we are using:

CallExpression[callee.name=$]

What does this mean? If you go to AST Explorer, and paste in a jQuery code, you will notice that for jQuery functions, the callee — which is an identifier — always has a name of $. Essentially, we have told ESLint to throw a warning whenever it comes across a function call that starts with a dollar sign. You can see that we can select properties of an object in the AST using bracket notation.

How we can get to the name of the callee for a call expression in AST
CallExpression.callee.name

For other ways to query the AST, you can have a look at ESLint’s official docs, where you can find all the supported selectors. At the writing of this tutorial, the following are supported:

The supported AST selectors in ESLint

Summary

In summary, the no-restricted-syntax in ESLint can be used flexibly to target any specific piece of code. Apart from no-restricted-syntax, and no-restricted-imports, you can also look into the following ESLint rules that can serve as an easier alternative to prevent certain codes to be committed:

  no-restricted-properties // Disallow certain properties on certain objects
no-restricted-globals // Disallow specified global variables
no-restricted-exports // Disallow specified names in exports

If you are further interested in how AST works, I recommend continuing with the tutorial below. Thank you for reading through, happy coding!

How to Automate Your Code Refactoring

📚 Get access to exclusive content

Want to get access to exclusive content? Support webtips to get access to tips, checklists, cheatsheets, and much more. ☕

Get access Support us
Read more on
🎉 Thank you for subscribing to our newsletter. x