Back to catalogue
ValidationPostToolUse· Write|Edit
TypeScript type checking
Type errors caught the moment a file is saved
Runs the TypeScript compiler in no-emit mode after a .ts/.tsx file is modified and reports typing errors back to the agent.
What does the TypeScript type checking hook do?
TypeScript type checking is a Claude Code PostToolUse hook matching Write|Edit. It fires automatically at that lifecycle event — outside the model, so it can't be skipped or forgotten. Type errors caught the moment a file is saved.
As a PostToolUse hook it runs after the action, reacting to what just happened rather than blocking it. Because it is a deterministic Node.js script, it executes on every matching event without relying on the model to remember — the guarantee that makes agentic workflows safe to automate.
Use cases
- Type safety
- Early error detection
- Strict TypeScript projects
Tags
#validation#typescript#typecheck#quality
settings.json fragment
{
"hooks": {
"PostToolUse": [
{
"hooks": [
{
"command": "node $CLAUDE_PROJECT_DIR/.claude/hooks/typecheck.mjs",
"type": "command"
}
],
"matcher": "Write|Edit"
}
]
}
}Script · .claude/hooks/typecheck.mjs
#!/usr/bin/env node
// @hookstack post-edit-typecheck
import { execSync } from "node:child_process";
// @hookstack post-edit-typecheck
// Vérifie les types TypeScript après écriture (PostToolUse Write|Edit)
import { readFileSync } from "node:fs";
import { dirname } from "node:path";
import { fileURLToPath } from "node:url";
function makeDefaultExec(projectDir) {
return (cmd) =>
execSync(cmd, { cwd: projectDir, stdio: "pipe", timeout: 30_000 });
}
export function run(
input,
{ exec, projectDir = process.env.CLAUDE_PROJECT_DIR } = {},
) {
const filePath = input.tool_input?.file_path ?? "";
if (!filePath || !/\.tsx?$/.test(filePath)) return null;
const cwd = projectDir ?? dirname(filePath);
const doExec = exec ?? makeDefaultExec(cwd);
try {
doExec("npx --no-install tsc --noEmit");
return null;
} catch (err) {
const output = err.stdout?.toString() ?? "";
return output ? { message: `TypeScript: ${output.trim()}\n` } : null;
}
}
/* v8 ignore next 5 */
if (process.argv[1] === fileURLToPath(import.meta.url)) {
const input = JSON.parse(readFileSync(0, "utf8"));
const result = run(input);
if (result?.message) process.stderr.write(result.message);
}