DEV Community

etorralba
etorralba

Posted on

Setting Up an Express API with TypeScript and Pre-commit Hooks Using Husky

TL;DR

Setting up an Express API with TypeScript can greatly enhance your development experience by providing strong typing and modern JavaScript features. This post covers the initial setup of an Express server with TypeScript, integration of linting with ESLint and Prettier, and ensuring code quality with Husky pre-commit hooks. For the complete code and setup details, please visit the GitHub repository.

Today, I am configuring an Express server with TypeScript and setting up pre-commit hooks using Husky to ensure code quality. This setup will include linting and testing the code before it's committed to version control, which is crucial for maintaining code standards and reducing bugs.

Create an Express Project

I'm establishing a mono repo for both the API and the client. Here’s the initial structure for the API:

├── LICENSE
├── README.md
├── api
│   ├── eslint.config.mjs
│   ├── .eslintrc.json
│   ├── .prettierrc
│   ├── node_modules
│   ├── package-lock.json
│   ├── package.json
│   ├── src
│   └── tsconfig.json
├── node_modules
│   └── husky
├── package-lock.json
└── package.json
Enter fullscreen mode Exit fullscreen mode

Configuring Project Dependencies

  1. Navigate to the API directory and initialize the Node.js project:
cd api/
npm init -y
Enter fullscreen mode Exit fullscreen mode
  1. Install necessary libraries including Express and TypeScript:
npm install express
npm install -D @types/express @types/node ts-node typescript nodemon
Enter fullscreen mode Exit fullscreen mode
  1. Create the following configuration files:
  2. tsconfig.json: This file sets up TypeScript for our project.
{
  "compilerOptions": {
    "target": "es2018",
    "module": "commonjs",
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "noImplicitReturns": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "removeComments": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "**/*.spec.ts"]
}
Enter fullscreen mode Exit fullscreen mode
  • src/server.ts: This is the main server file using Express.
import express, { Request, Response } from 'express';

const app = express();
const PORT = process.env.PORT || 3000;

app.get('/', (req: Request, res: Response) => {
  res.send('Hello World from Express and TypeScript!');
});

app.listen(PORT, () => {
  console.log(`Server running on http://localhost:${PORT}`);
});
Enter fullscreen mode Exit fullscreen mode
  1. Update the npm scripts for easier development and build processes:
"scripts": {
  "build": "tsc",
  "start": "node dist/server.js",
  "dev": "nodemon --watch 'src/**/*.ts' --exec 'ts-node' src/server.ts"
},
Enter fullscreen mode Exit fullscreen mode

Adding Linting to the Project

Linting helps maintain a standardized style across the project. Let's set up ESLint and Prettier:

  1. Install ESLint:
npm install -D eslint@8.57.0
Enter fullscreen mode Exit fullscreen mode
  1. Initialize ESLint and configure it:
npx eslint --init
Enter fullscreen mode Exit fullscreen mode

Choose the appropriate options for Node.js environment with ES modules.

  1. Update package.json with a lint command:
"scripts": {
  "lint": "eslint src --fix"
},
Enter fullscreen mode Exit fullscreen mode
  1. Install Prettier and its ESLint integration:
npm install -D prettier eslint-config-prettier eslint-plugin-prettier
Enter fullscreen mode Exit fullscreen mode
  1. Configure Prettier and update ESLint settings:
// .prettierrc
{
  "semi": true,
  "singleQuote": true
}
Enter fullscreen mode Exit fullscreen mode
// .eslintrc.json
{
  "extends": ["plugin:prettier/recommended"],
  "plugins": ["prettier"],
  "rules": {
    "prettier/prettier": "error"
  }
}
Enter fullscreen mode Exit fullscreen mode
  1. Add a format script to package.json:
"scripts": {
  "format": "prettier --write \"src/**/*.{js,jsx,ts,tsx,json,css,scss,md}\""
},
Enter fullscreen mode Exit fullscreen mode

Adding Pre-commit Hooks

Pre-commit hooks help enforce code standards by running lint and format checks before committing:

  1. Install Husky in the root folder:
npm install -D husky
Enter fullscreen mode Exit fullscreen mode
  1. Initialize Husky to create the .husky/ directory:
npx husky
Enter fullscreen mode Exit fullscreen mode
  1. Add a pre-commit file inside the .husky directory and provide the following command to lint and format code:
cd api && npm run lint && npm run format
Enter fullscreen mode Exit fullscreen mode

Further Improvements

  • Continuous Integration: Integrate with a CI/CD pipeline to run tests and deploy automatically.
  • Testing: Set up unit and integration tests using Jest or Mocha to ensure code quality and functionality.
  • Dockerization: Containerize the application with Docker for easier deployment and scalability.

This setup provides a robust foundation for developing an Express API with TypeScript, emphasizing code quality and developer productivity.

Top comments (0)