Back to catalogue
ValidationPostToolBatch
Typecheck after parallel file edits
Runs tsc --noEmit once after a full batch of parallel tool calls that include TypeScript file edits. Avoids redundant per-file tsc invocations and reports type errors back to Claude as context for the next turn.
Use cases
- Run a single TypeScript check after Claude edits multiple .ts/.tsx files in parallel
- Surface type errors immediately after batch refactors or code generation
- Reduce tsc invocation overhead versus per-file PostToolUse hooks
Providers & tags
Claude Code
#typescript#typecheck#batch#validation
settings.json fragment
{
"hooks": {
"PostToolBatch": [
{
"hooks": [
{
"command": "node $CLAUDE_PROJECT_DIR/.claude/hooks/post-tool-batch-typecheck.mjs",
"type": "command"
}
]
}
]
}
}Script · .claude/hooks/post-tool-batch-typecheck.mjs
#!/usr/bin/env node
// Vérifie les types TypeScript après un lot d'écritures (PostToolBatch)
import { readFileSync } from 'fs';
import { execSync } from 'child_process';
import { fileURLToPath } from 'url';
function defaultExec(cmd) {
return execSync(cmd, { stdio: 'pipe', timeout: 30_000 });
}
export function run(input, { exec = defaultExec } = {}) {
const calls = input.tool_calls ?? [];
const hasTs = calls.some(
(c) => ['Write', 'Edit'].includes(c.tool_name) && /\.tsx?$/.test(c.tool_input?.file_path ?? ''),
);
if (!hasTs) return null;
try {
exec('npx --no-install tsc --noEmit --pretty false 2>&1');
return null;
} catch (e) {
const out = (e.stdout ?? e.stderr ?? '').toString().slice(0, 2000);
return {
hookSpecificOutput: {
hookEventName: 'PostToolBatch',
additionalContext: `TypeScript errors after batch edit:\n${out}`,
},
};
}
}
/* 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) process.stdout.write(JSON.stringify(result));
}