By Alain Ngeukeu5 min read1113 words

From Manual Checks to Automated Guardrails: A TypeScript Developer's Guide to Husky

typescriptversioncontrol

By a developer, for developers who are tired of catching bugs after the fact.

Table of Content

  1. Why You Should Read This
  2. The Problem: Manual Checks Are Not Sustainable
  3. Git Hooks: The Native Solution
  4. Husky: The Team-Friendly Solution
  5. Setting It Up: From Zero to Automated Hooks
    1. Initialize Git
    2. Install Husky
    3. Define Scripts in package.json
    4. Create the Pre-Commit Hook
    5. Create the Pre-Push Hook
    6. Test Your Hooks
  6. Summary

Why You Should Read This

Every TypeScript developer has been there . you push code, the CI pipeline turns red, and you spend the next 20 minutes fixing a lint error or a type mismatch that a simple check would have caught in seconds. This article solves that problem permanently.

By the end, you will have a fully automated quality gate that runs lint, format, and type checks before every commit and every push, without typing a single command manually. Whether you are working solo or in a team, this setup will save you time, prevent regressions, and keep your codebase consistently clean.


The Problem: Manual Checks Are Not Sustainable

As a developer, three checks protect your codebase before code reaches the repository:

Lint Check — Linting analyzes source code statically (often via an abstract syntax tree) to catch syntax issues, unused variables, unreachable code, and risky patterns before runtime. In short, linting catches what’s wrong structurally and stylistically before the code runs.

Source - [https://www.browserstack.com/guide/what-is-linter](https://www.browserstack.com/guide/what-is-linter)

Format Check — Formatting tools like Prettier or Biome automatically standardize indentation, line breaks, quotes, and spacing without changing program semantics. This removes style debates from code reviews and lets reviewers focus on logic instead; in short, formatting enforces how it looks.

Source - [https://shishirsharma.com/2017/10/18/prettier-ending-code-style-debates-by-removing-choices/](https://shishirsharma.com/2017/10/18/prettier-ending-code-style-debates-by-removing-choices/)

Type Check — Type checking verifies that variables and functions are used with the correct data types, catching entire classes of bugs before the program runs. TypeScript, the dominant typed superset of JavaScript, adds static type analysis on top of plain JavaScript, and multiple reports summarizing Microsoft and industry research note roughly a 15% or greater reduction in common bugs when teams adopt TypeScript

Sources: - [https://hypersense-software.com/blog/2025/05/30/typescript-benefits-migration-development-company-guide/](https://hypersense-software.com/blog/2025/05/30/typescript-benefits-migration-development-company-guide/)

Running these three checks manually after every commit and every push is tedious, inconsistent, and easy to forget. The solution is Git hooks.


Git Hooks: The Native Solution

Git Hook

A Git hook is a built-in Git feature that runs scripts automatically when certain actions occur , such as committing or pushing. (See official docs : https://git-scm.com/docs/githooks)

However, native Git hooks have two critical limitations:

  • The .git/hooks folder is not tracked by Git, meaning it is never shared when the repo is cloned. Every developer must configure hooks manually, leading to inconsistent setups across the team.
  • Hooks are shell scripts that rely on Unix tools (bash, sh, grep), which work smoothly on Linux and macOS but can fail on Windows without Git Bash or WSL(Window Subsystem Linux) installed.

This is where Husky changes everything.


Husky: The Team-Friendly Solution

Husky is a Dog

Husky , https://typicode.github.io/husky/ , is a tool for Node.js projects that manages Git hooks inside the repository itself. Instead of .git/hooks, Husky stores hooks in a .husky/ folder that is committed to the repository.

Every developer who clones the project and installs dependencies automatically gets the same hooks.

Husky is not a replacement for Git hooks. It is a wrapper that makes them portable, consistent, and easy to configure.

Setting It Up: From Zero to Automated Hooks

Prerequisites

  • Git initialized in your project
  • Biome installed for lint and format: npm install --save-dev @biomejs/biome
  • TypeScript installed for type checking

1. Initialize Git

git init

2. Install Husky

npx husky init

3. Define Scripts in package.json

{ "scripts": { "lint": "biome lint .", "format": "biome format . --write", "typecheck": "tsc --noEmit", "check:fix": "npm run lint -- --fix --unsafe && npm run format && npm run typecheck", "check": "npm run lint && biome format . && npm run typecheck", "build": "next build" } }

Script reference:

CommandWhat it runsWhen to use
npm run lintbiome lint .Linting only
npm run formatbiome format . --writeFormatting only
npm run typechecktsc --noEmitType checking only, no output
npm run check:fixlint (auto-fix) + format + typecheckPre-commit
npm run checklint + format verify + typecheck (read-only)Pre-push
npm run buildnext buildProduction build

4. Create the Pre-Commit Hook

Create .husky/pre-commit:

#!/usr/bin/env sh # Load Husky's bootstrap script from the .husky/_/ directory . "$(dirname -- "$0")/_/husky.sh" # Run full check: lint (auto-fix) + format + typecheck # Triggered automatically before every git commit npm run check:fix

check:fix is the right choice here — it auto-fixes and formats before the commit is sealed, so no dirty code ever enters the repo.


5. Create the Pre-Push Hook

Create .husky/pre-push:

#!/usr/bin/env sh # Load Husky's bootstrap script from the .husky/_/ directory . "$(dirname -- "$0")/_/husky.sh" # Run full verification + production build # Triggered automatically before every git push # - check: lint + format verify + typecheck (no fixes, read-only) # - build: ensures the project compiles successfully before pushing npm run check && npm run build

The && operator ensures the build only runs if all checks pass — a failing lint or type error blocks the push immediately, saving unnecessary build time.


6. Test Your Hooks

echo "console.log('hook test')" >> test.ts git add test.ts git commit -m "test hooks" # triggers check:fix git push # triggers check + build

Summary

HookCommandPurpose
pre-commitnpm run check:fixFix + format + typecheck before commit
pre-pushnpm run check && npm run buildVerify + build before push

With this setup, broken code cannot enter your repository. Lint errors, formatting inconsistencies, type mismatches, and broken builds are all caught automatically , before they become anyone else's problem.

Thanks for reading !

Alain Ngongang