35 Static Type Checking Eslint Syntax Rules and Code Style Checks

35 Static Type Checking ESLint Syntax Rules and Code Style Checks #

Hello, I’m Shikawa.

In the previous lessons, we introduced testing in JavaScript, including functional tests such as unit tests and UI automation tests, as well as non-functional tests such as performance, security, and auxiliary tools. These tests are usually important steps in our software engineering pipeline before our products go live, because any issues discovered by these tests can directly impact whether our program can run correctly.

However, besides these tests, there are potential issues that, while not directly affecting our program, may indirectly pose system risks. According to Murphy’s Law, anything that can go wrong will go wrong. So, how do we address these potential risks in our code besides testing? This is where a linter code checking tool comes in.

Today, we will look at the code quality checking work using the tool ESLint, which checks both code quality and style.

Code Quality Tools #

In programming, the term “lint” refers to code that, although it can run, is not optimal in some way. This code may cause potential problems such as bugs, security risks, or issues with readability. A linter is a tool that detects problematic code in a program. Linting is the process of running a linter tool on code, fixing and removing problematic code until the linter no longer reports errors.

Lint is not a term exclusive to JavaScript. It originated from the C language, where a few common programming errors were not caught by the original compiler. As a result, an auxiliary tool called a linter was developed to scan source code files and find these issues. With the maturation of the C language and the strengthening of its definition to eliminate risks, coupled with warnings issued by compilers themselves, there was no longer a need for such additional code checking tools.

As mentioned before, JavaScript is a relatively flexible and lightweight language, which is both its strength and weakness. Because it lacks the strictness of languages like C or Java, especially for large projects, this flexibility means that developers themselves become the primary responsible parties for using the language effectively. Moreover, besides the lack of strictness in the language definition, JavaScript itself does not have an official compiler. Therefore, to this day, linting remains an important separate task in the code checking process that requires dedicated tools.

In fact, prior to ESLint, Douglas Crockford developed JSLint, an early JavaScript code quality checking tool. Its working principle is to scan the source code and return the approximate location and description of potential issues if found. These potential issues are not necessarily syntax errors; JSLint also focuses on style conventions and code structure issues. As mentioned earlier, unlike unit tests, JSLint does not confirm that the program can run properly. JSLint provides an additional way of discovering potential issues alongside unit tests. Because JSLint’s rules are stricter than the official definition of the ECMAScript language, it can be seen as a subset of JavaScript.

In later development, ESLint gradually became a more popular linter tool.

First, let’s briefly understand its components. The most core module of ESLint is the Linter, CLIEngine, and RuleTester.

  • The Linter is the core of the core; it does not have file I/O or interact directly with the console. Its main task is to validate code based on configured options.
  • The CLIEngine’s main purpose is to find source code files and configuration files. It includes logic for loading the configuration file, parser, plugins, and formatter. ESLint uses Espree as its parser.
  • The RuleTester is responsible for unit testing each check rule. RuleTester is internally wrapped with Mocha, yes, you read that right, ESLint uses Mocha as its internal unit testing tool. RuleTester mimics the interface of Mocha and can be used together with Mocha’s global test methods. Of course, in addition to Mocha, RuleTester can also be combined with other unit testing tools.

ESLint Components

Now let’s look at the relationship between ESLint, API, and CLI. ESLint is a file executed through the command line; in reality, it is just a wrapper that passes the command line as parameters to the CLI. When the CLI receives the parameters, it uses ESLint to execute the command. The API is the entry point for require("eslint"), exposing objects such as Linter, ESLint, RuleTester, and Source Code’s public classes.

Finally, let’s take a look at Source Code and Rules. As the names imply, they represent the source code and the built-in rules for code testing.

Code Style Check #

The above is an introduction to code style check tools. Now, let’s take a closer look at the installation and usage steps of ESLint. First, execute the following command to install ESLint.

npm init @eslint/config

During the initialization process, ESLint will ask about the usage scenarios, modularization types, framework used in your project, whether TypeScript is used, the runtime environment of the code, and the format of the config file, and so on. After that, the program will check if ESLint is already installed locally. If not, it will be installed first. You can choose the relevant package management tool before installation. Here, I am using NPM, but some students may choose YARN. After a series of choices, ESLint will run and complete the installation.

Image

Afterward, we can execute the code check with the following command.

npx eslint yourfile.js

Code Style Types #

So, what types of errors are usually checked during inspections? Before we discuss that, let’s first understand the purpose of code style. Because based on the test-driven design philosophy, without relevant test objectives, there would be no basis for inspections and error reporting. In summary, the code style usually serves two purposes:

  • Improving code quality
  • Standardizing code style

We can look at two examples through the following code. In the first example, using the constructor function to construct a function, similar to eval(), can execute the contents of a string. So this example not only has a code quality issue, but it can also pose a security risk.

// bad
const add = new Function('a', 'b', 'return a + b');

// still bad
const subtract = Function('a', 'b', 'return a - b');

In the next example, the expression for the object literal in the first line is very long. Although there is nothing wrong with the code quality itself, such a long sentence affects code readability. On the other hand, the second way of writing is more readable. Therefore, linter tools usually require that a line of code should not exceed 80 characters in length. This way, code readability can be improved.

Here, you may wonder, are there no advantages to writing code in one line? Actually, there are. If we write the code in one line, theoretically, it will occupy less space without line breaks, which can reduce the size of the file. However, this problem is usually not solved when writing the code, but it can be handled using a JS minifier after the program is written. When writing code, we always pay more attention to whether our code is readable for ourselves and our colleagues.

// Bad 
const foo = { "bar": "This is a bar.", "baz": { "qux": "This is a qux" }, "difficult": "to read" }; 

// Good
const foo = {
  "bar": "This is a bar.", 
  "baz": { "qux": "This is a qux" }, 
  "difficult": "to read" 
}; 

From the above examples, we can see that a linter is a way to make our code better. However, there are many similar issues in JavaScript. At the same time, sometimes people may have different definitions of “good”. So, what should we do when faced with such a large number of rules and different definitions of code style?

Let’s start with the number of rules. Here, ESLint has already organized some commonly used rules for us. We can use ESLint’s built-in rules as a baseline and customize them as needed. The built-in rules are divided into problems, suggestions, layout, and formatting. The purpose of the problems and suggestions is mainly to improve code quality, while the purpose of layout and formatting is to standardize code writing style.

Next, let’s look at what to do when different individuals or teams have their own style. In such situations, developers can meet different requirements through custom rules, and these rules can also be shared. For example, Airbnb has summarized its own JavaScript code style guide and open-sourced the relevant ESLint configuration for other developers to use. So, even if we are the only person writing code, is it necessary to use a linter? The answer is yes, because even in the case of only one maintainer, we should still strive to maintain a consistent code style.

ESLint can also be used in conjunction with third-party libraries such as Angular and React through plugins.

Extension: Code Formatting Tool #

When we use ESLint, our main goal is to write higher quality code, followed by code beautification. One reason why some projects use linters is to enforce consistent coding styles, so that when a development team shares the same product or project codebase, they can use compatible code conventions. This includes code indentation rules, as well as rules such as whether to use single or double quotes, or whether there should be a space between the for keyword and the following right parenthesis.

In addition to linters, there is a code formatting tool called Prettier. Its working principle is also to parse and format code. For example, if we write the following function, in terms of functionality, it is valid, but the formatting does not conform to common practice.

function HelloWorld({greeting = "hello", greeted = '"World"', silent = false, onMouseOver,}) {
}

Running Prettier on this code can fix the indentation, add missing line breaks, and make the code more readable.

function HelloWorld({
  greeting = "hello",
  greeted = '"World"',
  silent = false,
  onMouseOver,
}) {}

When using Prettier, if using the --write option, it formats the specified file in place instead of creating a formatted copy. If you use Git to manage your source code, you can use the --write option in a commit hook to automatically format the code before committing. It would be more convenient if you configure your code editor to run Prettier automatically on file save.

Image

Prettier is configurable. You can choose the line length limit, indentation level, whether to use semicolons, and whether to use single or double quotes to wrap strings. Although it only has a few options, overall, Prettier’s default options are very reasonable and require minimal changes to achieve the desired effect. At the same time, Prettier can also be used in conjunction with eslint-config-prettier and ESLint mentioned earlier.

Summary #

In today’s lecture, we saw that while JavaScript provides us with flexibility in writing code, it also comes with many potential problems. As a code inspection tool, linter can help us minimize the risks of code quality issues. At the same time, we can also use code formatting tools like Prettier to make our code clearer and more readable, both for ourselves and for other developers.

Recently, there has been a popular saying that “pessimistic people are always right, optimistic people are always successful.” So some people may feel that Murphy’s Law is too pessimistic. However, when the program is complex enough and there are enough users, things that can go wrong will go wrong. Therefore, I believe that to develop a successful application, developers should be a combination of pessimism and optimism. Pessimism allows us to keep the foundation of stable program operation, while optimism drives us to constantly break through, innovate, and optimize. It is the space between these two that determines the development of our program.

Thought question #

Earlier, we mentioned that ESLint uses the parser Espree, which is based on JQuery’s Esprima but with improvements. Do you know why ESLint didn’t continue using Esprima and instead created a new parser?

Please feel free to share your thoughts, exchange learning experiences, or ask questions in the comments section. If you find it valuable, you are also encouraged to share today’s content with more friends. See you in the next class!