javascriptnode.jseslint

How to make ESLint catch ReferenceErrors


I use ESLint from Node.js to check my code and it seems not to catch ReferenceErrors. Here is a minimal example, mre.js:

console.log(obj);
let obj = 2;

When I run ESLint, I get no warnings:

$ ./node_modules/.bin/eslint mre.js

I updated ESLint and confirm it is the latest version (9.2.6):

$ npm update eslint
$ npm info eslint version           
9.26.0

How can I make ESLint catch ReferenceErrors, or what is a linter that catches them?


Solution

  • You should enable the no-undef and no-use-before-define rule. The two should capture most cases where you try to access something that can lead to a ReferenceError.

    no-use-before-define

    Note that no-use-before-define does catch some cases where there will not be a reference error, like:

    console.log(foo); //error here
    var foo = 42;
    
    fn(); // error here
    function fn() {}
    

    Of the two, the var example is probably OK to have an error: first, you should not be using var and second, even when using it, trying to reference it before assignment suggests something wrong with the code structure or logic.

    The function example can be arguable. Some style guides insist on functions being defined first before used, others may actually prefer them at the end.

    The no-use-before-define rule has options determining what is allowed to be referenced before definition. To allow this for functions, the option is called functions, so it can be configured like this:

    {
        "no-use-before-define": [
            "error", 
            {
                "functions": true
            }
        ]
    }
    

    no-undef

    The rule straight up disallows using something that is not known to exist. That is some times overly strict - if you use scripts on a page like:

    <script src="a.js"></script>
    <script src="b.js"></script>
    

    Where a.js creates a global and b.js tries to use it, then ESLint will have no knowledge of that and will flag a problem in b.js. In modern JavaScript you should be using modules and importing things from other modules. That immediately resolves this issue. But if still needed, you can specify globals in the configuration, this dealing with the no-undef check. This might be useful in older code bases.

    Some built-ins might not be known to ESLint, like (commonly) console. But there might be other built-in globals that are exposed by the environment (e.g., in Node.js) or a framework (e.g., Mocha). ESLint also has predefined collections of globals that can be included by mentioning the environment. For example, if you are linting Node.js code you can just include all globals related to it in the configuration, without having to define them one by one.