Skip to content

Instantly share code, notes, and snippets.

@hekystyle
Last active October 1, 2025 13:41
Show Gist options
  • Select an option

  • Save hekystyle/19ec7b28889585625405d5ac67fdbc24 to your computer and use it in GitHub Desktop.

Select an option

Save hekystyle/19ec7b28889585625405d5ac67fdbc24 to your computer and use it in GitHub Desktop.
Mute all TS errors by @ts-expect-error comment
// generate output using this command: `./node_modules/.bin/tsc --noEmit > ts-errors.txt`
// then apply directive using command: `jscodeshift --v --extensions="ts,tsx" -t ./transform.ts ./src`
import type { Transform } from 'jscodeshift';
import { readFileSync } from 'node:fs';
import path, { normalize } from 'node:path';
import { cwd } from 'node:process';
import R from 'ramda';
function applyIgnoreDirective(line: string, errorIndices: number[]): string[] {
const leadingWhitespaceMatch = line.match(/^(\s*)/);
const indentation = leadingWhitespaceMatch ? (leadingWhitespaceMatch[1] ?? '') : '';
line = line.trimStart();
errorIndices = errorIndices.map((index) => index - indentation.length);
const chunks: string[] = [];
let lastIndex = 0;
for (const currentIndex of errorIndices) {
const chunk = line.slice(lastIndex, currentIndex).trim();
if (chunk !== '') {
chunks.push(`${indentation}${chunk}`);
}
chunks.push(`${indentation}// @ts-expect-error - FIXME: Ignored TypeScript error`);
lastIndex = currentIndex;
}
chunks.push(indentation + line.slice(lastIndex));
return chunks;
}
const filePath = path.join(cwd(), 'ts-errors.txt');
const errors = readFileSync(filePath, 'utf8')
.split('\n')
.filter((line) => line.match(/\.tsx?\(\d+,\d+\)/))
.map((row) => {
const match = row.match(/(.*\.tsx?)\((\d+),(\d+)\): error TS(\d+)/);
const [_, file = '', line, column, errorCode] = match ?? [];
return {
file: normalize(file),
line: Number(line),
column: Number(column),
errorCode: Number(errorCode),
};
});
const errorsByFile = R.groupBy((error) => error.file, errors);
const ignoredErrorCodesSet = new Set([
6133, // 'x' is declared but its value is never read.
]);
const transform: Transform = (file, api) => {
const fileErrors = errorsByFile[file.path] ?? [];
const errorsByLine = R.groupBy((error) => error.line.toString(), fileErrors);
if (fileErrors.length === 0) {
console.log('No errors in file', file.path);
return file.source;
}
return file.source
.split('\n')
.map<string[]>((line, index) => {
const lineErrors = errorsByLine[(index + 1).toString()];
if (!lineErrors) return [line];
return applyIgnoreDirective(
line,
lineErrors.filter((error) => !ignoredErrorCodesSet.has(error.errorCode)).map((error) => error.column - 1),
);
})
.flat()
.join('\n');
};
export default transform;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment