Why a Next.js lint check can miss TypeScript errors

#nextjs#typescript#lint#typecheck

Linting and type checking can look like the same safety net, but they catch different problems. I learned that when a passing workflow still produced a failed build.

Why linting was not enough#

I had a continuous integration (CI) workflow for a Next.js and TypeScript project. The workflow only ran the linter:

linting.yml
- name: Install dependencies
run: npm ci
- name: Lint code
run: npm run lint

The lint check passed, but the production build failed during type checking. The linter and TypeScript compiler were checking different problems.

Add an explicit type check#

I fixed the gap by running the TypeScript compiler before the linter.

First, add a typecheck script to package.json:

package.json
{
"scripts": {
"typecheck": "tsc --noEmit"
}
}

Then add the new step to the CI workflow:

linting.yml
- name: Install dependencies
run: npm ci
# Add a type-checking step.
- name: Typecheck
run: npm run typecheck
- name: Lint code
run: npm run lint

The workflow now stops on type errors before it starts the production build. For more context, see the related Next.js discussion.