DEV Community

Eduardo Henrique Gris
Eduardo Henrique Gris

Posted on

React and typescript components lib, part 2: code standardization with typescript-eslint and prettier

Introduction

Portuguese version: Biblioteca de componentes React e typescript, parte 2: padronização de código com typescript-eslint e prettier

Last month, I started part 1 of creating a React component library with TypeScript, focusing on the initial setup and publishing. Now, in this article, the library will be enhanced by defining code standardization rules using typescript-eslint and prettier. The goal is to make this article more practical in terms of implementation. For those who want a deeper understanding of how it works in general, I wrote the article Typescript-eslint + prettier for code standardization in React with Typescript earlier this month.

Libs

typescript-eslint: responsible for analyzing the code to identify and resolve issues
prettier: responsible for code formatting

Setup libs

Addition of typescript-eslint, prettier and the plugins that will be used:

yarn add typescript-eslint eslint @eslint/js prettier eslint-plugin-react --dev

  • typescript-eslint: allows eslint to parse typescript syntax and provides linting rules for typescript
  • eslint: dependency required by typescript-eslint
  • @eslint/js: provides eslint rules
  • prettier: add lib responsible for code formatting
  • eslint-plugin-react: brings linting rules for React

At the time of writing this article, the following versions were generated:

"@eslint/js": "^9.19.0",
"eslint": "^9.19.0",
"eslint-plugin-react": "^7.37.4",
"prettier": "^3.4.2",
"typescript-eslint": "^8.23.0"
Enter fullscreen mode Exit fullscreen mode

Configuration file

For prettier a configuration file named .prettierrc is created at the root, empty since the default rules of the library are not being modified.
For typescript-eslint a configuration file named eslint.config.mjs is created at the root, that will allow code verification to run and define the rules that will be used for analysis. Initially, the recommended rules from eslint, typescript-eslint and react will be used:

  • eslint.config.mjs
import eslint from "@eslint/js";
import reactPlugin from "eslint-plugin-react";
import tseslint from "typescript-eslint";

export default tseslint.config(
  eslint.configs.recommended,
  tseslint.configs.recommendedTypeChecked,
  {
    languageOptions: {
      parserOptions: {
        projectService: true,
        tsconfigRootDir: import.meta.dirname,
      },
    },
  },
  reactPlugin.configs.flat.recommended,
  reactPlugin.configs.flat['jsx-runtime'],
  {
    settings: {
      react: {
        version: "detect",
      },
    }
  }
);
Enter fullscreen mode Exit fullscreen mode
  • tseslint.config: where the typescript-eslint configurations are specified
  • eslint.configs.recommended: applies the recommended eslint rules in the code analysis
  • tseslint.configs.recommendedTypeChecked: applies the recommended typescript rules in the code analysis, that additionally require type information
  • projectService: indicates to ask typescript's type checking service for each source file's type information
  • import.meta.dirname: tells the parser the absolute path of project's root directory
  • reactPlugin.configs.flat.recommended: applies the recommended React rules in the code analysis
  • reactPlugin.configs.flat['jsx-runtime']: required for React 17+ to work with the new jsx runtime introduced in that version
  • settings: it is set to detect the version of React being used in the project

Customization of rules

There are some rules that I believe would be interesting to modify or add compared to the recommended ones. To do this, it will be necessary to update the typescript-eslint configuration file by adding rules:

  • eslint.config.mjs
import eslint from "@eslint/js";
import reactPlugin from "eslint-plugin-react";
import tseslint from "typescript-eslint";

export default tseslint.config(
  eslint.configs.recommended,
  tseslint.configs.recommendedTypeChecked,
  {
    languageOptions: {
      parserOptions: {
        projectService: true,
        tsconfigRootDir: import.meta.dirname,
      },
    },
  },
  reactPlugin.configs.flat.recommended,
  reactPlugin.configs.flat['jsx-runtime'],
  {
    settings: {
      react: {
        version: "detect",
      },
    },
    rules: {
      "no-console": "warn",
      "no-duplicate-imports": "error",
      "react/destructuring-assignment": "error",
      "react/jsx-no-useless-fragment": "error",
      "@typescript-eslint/no-unused-vars": "off",
    }
  }
);
Enter fullscreen mode Exit fullscreen mode
Source Rule Default (with recommended) With customization
eslint no-console disabled enabled, returns a warning if there is a console.log in the code
eslint no-duplicate-imports disabled enabled, returns an error if there are duplicate imports
plugin react react/destructuring-assignment disabled enabled, returns an error if the props are not destructured
plugin react react/jsx-no-useless-fragment disabled enabled, returns an error if there is an unnecessary fragment
typescript-eslint @typescript-eslint/no-unused-vars enabled disabled, does not return an error for unused variables or parameters

The reason for disabling the @typescript-eslint/no-unused-vars rule is that the component library being created is above version 17 of React. With the rule enabled, an error is returned because the library component definitions include: import React from "react";
In the development of the library, this import wouldn't be necessary, but it's included because the application that adds the library may be using a version of React lower than 17, which requires the import to be present. For this reason, the rule was disabled.

package.json

For now, the package.json should look something like the below:

{
  "name": "react-example-lib",
  "version": "0.1.0",
  "main": "dist/cjs/index.js",
  "module": "dist/esm/index.js",
  "types": "dist/index.d.ts",
  "files": [
    "dist"
  ],
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "https://github.com/griseduardo/react-example-lib.git"
  },
  "scripts": {
    "build": "rollup -c --bundleConfigAsCjs",
  },
  "devDependencies": {
    "@eslint/js": "^9.19.0",
    "@rollup/plugin-commonjs": "^28.0.2",
    "@rollup/plugin-node-resolve": "^16.0.0",
    "@rollup/plugin-terser": "^0.4.4",
    "@rollup/plugin-typescript": "11.1.6",
    "@types/react": "^19.0.8",
    "eslint": "^9.19.0",
    "eslint-plugin-react": "^7.37.4",
    "prettier": "^3.4.2",
    "react": "^19.0.0",
    "react-dom": "^19.0.0",
    "rollup": "^4.30.1",
    "rollup-plugin-dts": "^6.1.1",
    "rollup-plugin-peer-deps-external": "^2.2.4",
    "styled-components": "^6.1.14",
    "typescript": "^5.7.3",
    "typescript-eslint": "^8.23.0"
  },
  "peerDependencies": {
    "react": "^19.0.0",
    "react-dom": "^19.0.0",
    "styled-components": "^6.1.14"
  }
}
Enter fullscreen mode Exit fullscreen mode

Scripts will be added to ensure code standardization using the rules defined in the typescript-eslint configuration file. Additionally, the version will be changed to 0.2.0, as a new version of the library will be released:

{
  "name": "react-example-lib",
  "version": "0.2.0",
  "main": "dist/cjs/index.js",
  "module": "dist/esm/index.js",
  "types": "dist/index.d.ts",
  "files": [
    "dist"
  ],
  "license": "MIT",
  "repository": {
    "type": "git",
    "url": "https://github.com/griseduardo/react-example-lib.git"
  },
  "scripts": {
    "build": "rollup -c --bundleConfigAsCjs",
    "lint-src": "eslint src",
    "lint-src-fix": "eslint src --fix",
    "format-src": "prettier src --check",
    "format-src-fix": "prettier src --write"
  },
  "devDependencies": {
    "@eslint/js": "^9.19.0",
    "@rollup/plugin-commonjs": "^28.0.2",
    "@rollup/plugin-node-resolve": "^16.0.0",
    "@rollup/plugin-terser": "^0.4.4",
    "@rollup/plugin-typescript": "11.1.6",
    "@types/react": "^19.0.8",
    "eslint": "^9.19.0",
    "eslint-plugin-react": "^7.37.4",
    "prettier": "^3.4.2",
    "react": "^19.0.0",
    "react-dom": "^19.0.0",
    "rollup": "^4.30.1",
    "rollup-plugin-dts": "^6.1.1",
    "rollup-plugin-peer-deps-external": "^2.2.4",
    "styled-components": "^6.1.14",
    "typescript": "^5.7.3",
    "typescript-eslint": "^8.23.0"
  },
  "peerDependencies": {
    "react": "^19.0.0",
    "react-dom": "^19.0.0",
    "styled-components": "^6.1.14"
  }
}
Enter fullscreen mode Exit fullscreen mode
  • lint-src: it will check all the files inside the src folder (it is where the component definitions are located), following the rules defined in the typescript-eslint configuration file
  • lint-src-fix: it will auto-correct all the files inside the src folder, following the rules defined in the typescript-eslint configuration file
  • format-src: it will check all the files inside the src folder formatting, following the prettier rules
  • format-src-fix: it will auto-correct the formatting for all the files inside the src folder, following the prettier rules

CHANGELOG file

For now, the CHANGELOG.md is as follows:

## 0.1.0

_Jan. 29, 2025_

- initial config
Enter fullscreen mode Exit fullscreen mode

Since a new version will be released, information about what was modified will be added in the file:

## 0.2.0

_Fev. 24, 2025_

- setup typescript-eslint and prettier
- add custom rules

## 0.1.0

_Jan. 29, 2025_

- initial config
Enter fullscreen mode Exit fullscreen mode

Folder structure

The folder structure is as follows, with the modification of some files and the addition of two configuration files at the root:

Image description

Publication of a new version

The first step to be performed is to check if the rollup execution runs successfully. To do this, yarn build will be executed in the terminal, as defined in package.json.
If it executes successfully, proceed with publishing the new version of the library: npm publish --access public

Conclusion

The idea of this article was to add code standardization rules for the component library being created, using typescript-eslint and prettier.
Here is the repository on github and the library on npmjs with the new modifications.

Top comments (0)