Skip to content

Commit 9099b0f

Browse files
fix: fix the pre-commit hook for tsc (#34275)
Co-authored-by: Mehmet Salih Yavuz <[email protected]>
1 parent 77ffe65 commit 9099b0f

File tree

2 files changed

+87
-16
lines changed

2 files changed

+87
-16
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ repos:
7676
files: ^docs/.*\.(js|jsx|ts|tsx)$
7777
- id: type-checking-frontend
7878
name: Type-Checking (Frontend)
79-
entry: bash -c './scripts/check-type.js package=superset-frontend excludeDeclarationDir=cypress-base'
79+
entry: ./scripts/check-type.js package=superset-frontend excludeDeclarationDir=cypress-base
8080
language: system
8181
files: ^superset-frontend\/.*\.(js|jsx|ts|tsx)$
8282
exclude: ^superset-frontend/cypress-base\/

scripts/check-type.js

Lines changed: 86 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ const PACKAGE_ARG_REGEX = /^package=/;
3232
const EXCLUDE_DECLARATION_DIR_REGEX = /^excludeDeclarationDir=/;
3333
const DECLARATION_FILE_REGEX = /\.d\.ts$/;
3434

35+
// Configuration for batching and fallback
36+
const MAX_FILES_FOR_TARGETED_CHECK = 20; // Fallback to full check if more files
37+
const BATCH_SIZE = 10; // Process files in batches of this size
38+
3539
void (async () => {
3640
const args = process.argv.slice(2);
3741
const {
@@ -45,27 +49,94 @@ void (async () => {
4549
}
4650

4751
const packageRootDir = await getPackage(packageArg);
48-
const updatedArgs = removePackageSegment(remainingArgs, packageRootDir);
49-
const argsStr = updatedArgs.join(" ");
52+
const changedFiles = removePackageSegment(remainingArgs, packageRootDir);
5053

51-
const excludedDeclarationDirs = getExcludedDeclarationDirs(
52-
excludeDeclarationDirArg
54+
// Filter to only TypeScript files
55+
const tsFiles = changedFiles.filter(file =>
56+
/\.(ts|tsx)$/.test(file) && !DECLARATION_FILE_REGEX.test(file)
5357
);
58+
59+
console.log(`Type checking ${tsFiles.length} changed TypeScript files...`);
60+
61+
if (tsFiles.length === 0) {
62+
console.log("No TypeScript files to check.");
63+
exit(0);
64+
}
65+
66+
// Decide strategy based on number of files
67+
if (tsFiles.length > MAX_FILES_FOR_TARGETED_CHECK) {
68+
console.log(`Too many files (${tsFiles.length} > ${MAX_FILES_FOR_TARGETED_CHECK}), running full type check...`);
69+
await runFullTypeCheck(packageRootDir, excludeDeclarationDirArg);
70+
} else {
71+
console.log(`Running targeted type check on ${tsFiles.length} files...`);
72+
await runTargetedTypeCheck(packageRootDir, tsFiles, excludeDeclarationDirArg);
73+
}
74+
})();
75+
76+
/**
77+
* Run full type check on the entire project
78+
*/
79+
async function runFullTypeCheck(packageRootDir, excludeDeclarationDirArg) {
80+
const packageRootDirAbsolute = join(SUPERSET_ROOT, packageRootDir);
81+
const tsConfig = getTsConfig(packageRootDirAbsolute);
82+
// Use incremental compilation for better caching
83+
const command = `--noEmit --allowJs --incremental --project ${tsConfig}`;
84+
85+
await executeTypeCheck(packageRootDirAbsolute, command);
86+
}
87+
88+
/**
89+
* Run targeted type check on specific files, with batching
90+
*/
91+
async function runTargetedTypeCheck(packageRootDir, tsFiles, excludeDeclarationDirArg) {
92+
const excludedDeclarationDirs = getExcludedDeclarationDirs(excludeDeclarationDirArg);
5493
let declarationFiles = await getFilesRecursively(
55-
packageRootDir,
94+
join(SUPERSET_ROOT, packageRootDir),
5695
DECLARATION_FILE_REGEX,
5796
excludedDeclarationDirs
5897
);
5998
declarationFiles = removePackageSegment(declarationFiles, packageRootDir);
60-
const declarationFilesStr = declarationFiles.join(" ");
6199

62100
const packageRootDirAbsolute = join(SUPERSET_ROOT, packageRootDir);
63101
const tsConfig = getTsConfig(packageRootDirAbsolute);
64-
const command = `--noEmit --allowJs --composite false --project ${tsConfig} ${argsStr} ${declarationFilesStr}`;
65102

103+
// Process files in batches to avoid command line length limits
104+
const batches = [];
105+
for (let i = 0; i < tsFiles.length; i += BATCH_SIZE) {
106+
batches.push(tsFiles.slice(i, i + BATCH_SIZE));
107+
}
108+
109+
let hasErrors = false;
110+
111+
for (const [batchIndex, batch] of batches.entries()) {
112+
if (batches.length > 1) {
113+
console.log(`\nProcessing batch ${batchIndex + 1}/${batches.length} (${batch.length} files)...`);
114+
}
115+
116+
const argsStr = batch.join(" ");
117+
const declarationFilesStr = declarationFiles.join(" ");
118+
// For targeted checks, keep composite false since we're passing specific files
119+
const command = `--noEmit --allowJs --composite false --project ${tsConfig} ${argsStr} ${declarationFilesStr}`;
120+
121+
try {
122+
await executeTypeCheck(packageRootDirAbsolute, command);
123+
} catch (error) {
124+
hasErrors = true;
125+
// Continue processing other batches to show all errors
126+
}
127+
}
128+
129+
if (hasErrors) {
130+
exit(1);
131+
}
132+
}
133+
134+
/**
135+
* Execute the TypeScript type check command
136+
*/
137+
async function executeTypeCheck(packageRootDirAbsolute, command) {
66138
try {
67139
chdir(packageRootDirAbsolute);
68-
// Please ensure that tscw-config is installed in the package being type-checked.
69140
const tscw = packageRequire("tscw-config");
70141
const child = await tscw`${command}`;
71142

@@ -77,14 +148,16 @@ void (async () => {
77148
console.error(child.stderr);
78149
}
79150

80-
exit(child.exitCode);
151+
if (child.exitCode !== 0) {
152+
throw new Error(`Type check failed with exit code ${child.exitCode}`);
153+
}
81154
} catch (e) {
82-
console.error("Failed to execute type checking:", e);
83-
console.error("Package:", packageRootDir);
155+
console.error("Failed to execute type checking:", e.message);
84156
console.error("Command:", `tscw ${command}`);
85-
exit(1);
157+
throw e;
86158
}
87-
})();
159+
}
160+
88161

89162
/**
90163
*
@@ -112,7 +185,6 @@ function shouldExcludeDir(fullPath, excludedDirs) {
112185
*
113186
* @returns {Promise<string[]>}
114187
*/
115-
116188
async function getFilesRecursively(dir, regex, excludedDirs) {
117189
try {
118190
const files = await readdir(dir, { withFileTypes: true });
@@ -186,7 +258,6 @@ function getExcludedDeclarationDirs(excludeDeclarationDirArg) {
186258
* @param {RegExp[]} regexes
187259
* @returns {{ matchedArgs: (string | undefined)[], remainingArgs: string[] }}
188260
*/
189-
190261
function extractArgs(args, regexes) {
191262
/**
192263
* @type {(string | undefined)[]}

0 commit comments

Comments
 (0)