Mastering Pre-commit Hooks in TypeScript: A Developer’s Guide to Clean Code

As developers, we’ve all been there – pushing code only to realize it doesn’t follow the team’s coding standards or contains formatting inconsistencies. This is where pre-commit hooks come into play, particularly for TypeScript projects. Let’s explore how these tools can make your development process smoother and more efficient.

What are Pre-commit Hooks?

Pre-commit hooks are scripts that run automatically before a commit is completed. Think of them as your code’s quality control checkpoint. They examine the changes you will commit and ensure they meet your project’s standards.

Why Do We Need Pre-commit Hooks?

1. IDE Agnostic Solution

One of the biggest advantages of pre-commit hooks is that they work regardless of which IDE your team uses; whether someone prefers VS Code, WebStorm, or Sublime Text, pre-commit hooks ensure consistent code quality across the team.

For example:

# Sample pre-commit hook configuration
#!/bin/sh
npm run lint-staged

2. Smart and Efficient Processing

Pre-commit hooks are intelligent – they only check the files that are being changed in the current commit. This means:

▪️Faster execution times
▪️Immediate feedback on your changes
▪️No waste of resources checking unchanged files

Setting Up Pre-commit Hooks for TypeScript

Let’s set up a basic pre-commit hook system:

1. First, install the necessary packages:

npm install --save-dev husky lint-staged prettier eslint 
@typescript-eslint/parser @typescript-eslint/eslint-plugin

2. Configure Husky in your package.json:

{
   "husky": {
     "hooks": {
        "pre-commit": "lint-staged"
     }
},
"lint-staged": {
  "*.{ts,tsx}": [
    "prettier --write",
    "eslint --fix",
    "git add"
  ]
 }
}

The Power of Code Formatting with Prettier

Why Format Code?

Code formatting might seem like a cosmetic concern, but it’s much more than that:

1. Readability: Consistent formatting makes code easier to read and understand.

// Hard to read
function calculateTotal(items:number[],tax:number,discount?:number):number{
return items.reduce((sum,item)=>sum+item,0)*(1+tax)*(discount?1-discount:1)}

// After Prettier formatting
function calculateTotal(
  items: number[],
  tax: number,
  discount?: number
): number {
  return items.reduce((sum, item) => sum + item, 0) * (1 + tax) * (discount ? 1 - discount : 1);
}

2. Smaller Diffs: When everyone uses the same formatting rules, code diffs in version control focus on actual logic changes rather than styling differences.

3. Time-Saving: No more debates about tabs vs. spaces or line length – Prettier handles it automatically.

Leveraging TypeScript’s Full Potential with Linters

TypeScript is powerful, but you need proper linting to use it effectively. ESLint with TypeScript support helps you:

1. Catch Type-Related Issues Early:

// ESLint will catch this error
function processUser(user: any) { // Warning: Avoid using 'any'
  return user.name.toLowerCase();
}

// Better approach
interface User {
  name: string;
}

function processUser(user: User) {
  return user.name.toLowerCase();
}

2. Enforce Best Practices:

// ESLint will warn about implicit any
function add(a, b) { // Warning: Parameters lack type annotations
  return a + b;
}

// Correct version
function add(a: number, b: number): number {
  return a + b;
}

Enforcing Modern Coding Standards

Pre-commit hooks help you stay updated with the latest TypeScript features and best practices:

1. Automatic Detection of Deprecated Features:

// Old approach (will be flagged)
interface Person {
  name: string;
  getAge(): number;
}

// Modern approach using more TypeScript features
type Person = {
  name: string;
  age: () => number;
};

2. Encouraging Modern JavaScript Features:

// Will be flagged by ESLint
var x = 5;
function oldStyle() {
  return x;
}

// Modern approach
const x = 5;
const modernStyle = () => x;

Launch Scalable, High-Quality Products With Our Engineering Experts

Best Practices for Pre-commit Hooks

1. Keep it Fast: Only run necessary checks to avoid slowing down the commit process.

2. Configure Appropriately: Create a .prettierrc file:

{
  "singleQuote": true,
  "trailingComma": "es5",
  "printWidth": 100,
  "tabWidth": 2
}

3. ESLint Configuration:

{
  "parser": "@typescript-eslint/parser",
  "plugins": ["@typescript-eslint"],
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended"
  ]
}

Common Issues and Solutions

1. Hook Takes Too Long:

▪️Only run checks on changed files
▪️Use cache mechanisms in ESLint
▪️Configure Prettier to run only on necessary files

2. False Positives:

// If you need to disable a rule occasionally
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function legacy(data: any) {
  // Legacy code handling
}

Benefits of Team Collaboration

▪️Consistent Codebase: Everyone’s code looks the same, making review easier.

▪️Reduced Code Review Time: Automated formatting means reviewers can focus on logic.

▪️Better Onboarding: New developers automatically follow team standards.

coma

Conclusion

Pre-commit hooks in TypeScript projects are more than just a tool; they are your first line of defense against code inconsistencies and potential issues. By implementing them, you ensure code quality across different IDEs, get immediate feedback on your changes, maintain consistent styling, use TypeScript to its full potential, and stay updated with modern coding standards.

Remember, the goal is to make development smoother, not to create obstacles. Configure your hooks wisely, and they’ll become an invaluable part of your development workflow.

 

Keep Reading

Keep Reading

  • Service
  • Career
  • Let's create something together!

  • We’re looking for the best. Are you in?