Prevent Imports From Being Used With ESLint

Prevent Imports From Being Used With ESLint

And other expressions using AST selectors
Ferenc Almasi β€’ Last updated 2021 November 11 β€’ Read time 5 min read
Learn how you can use ESLint rules to prevent the use of certain imports and function calls.
  • twitter
  • facebook
JavaScript

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:

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

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:

Copied to clipboard!
// 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

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.


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:

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

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

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

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:

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

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
Looking to improve your skills? Check out our interactive course to master JavaScript from start to finish.
Master JavaScriptinfo Remove ads

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
  • twitter
  • facebook
JavaScript
Did you find this page helpful?
πŸ“š More Webtips
Mentoring

Rocket Launch Your Career

Speed up your learning progress with our mentorship program. Join as a mentee to unlock the full potential of Webtips and get a personalized learning experience by experts to master the following frontend technologies:

Courses

Recommended

This site uses cookies We use cookies to understand visitors and create a better experience for you. By clicking on "Accept", you accept its use. To find out more, please see our privacy policy.