Extensible hook system for intercepting and customizing type checking lifecycle events. The plugin provides a comprehensive set of hooks using webpack's tapable library, allowing other plugins and tools to integrate with the type checking process.
Complete set of lifecycle hooks for the type checking process.
/**
* Plugin hooks for extensibility and lifecycle management
*/
interface ForkTsCheckerWebpackPluginHooks {
/**
* Called before type checking starts
* Async waterfall hook that can modify the files change and compilation
*/
start: AsyncSeriesWaterfallHook<[FilesChange, webpack.Compilation]>;
/**
* Called while waiting for type checking to complete
* Sync hook for status updates and progress reporting
*/
waiting: SyncHook<[webpack.Compilation]>;
/**
* Called when type checking is canceled
* Sync hook for cleanup and status updates
*/
canceled: SyncHook<[webpack.Compilation]>;
/**
* Called when an error occurs during type checking
* Sync hook for error handling and reporting
*/
error: SyncHook<[unknown, webpack.Compilation]>;
/**
* Called when type checking issues are found
* Sync waterfall hook that can modify the issues array
*/
issues: SyncWaterfallHook<[Issue[], webpack.Compilation | undefined], void>;
}Function to access plugin hooks for a given webpack compiler.
/**
* Get plugin hooks for a webpack compiler
* @param compiler - Webpack compiler or multi-compiler instance
* @returns Plugin hooks object for tapping into lifecycle events
*/
function getPluginHooks(
compiler: webpack.Compiler | webpack.MultiCompiler
): ForkTsCheckerWebpackPluginHooks;Intercept and modify the type checking start process.
import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin';
// In another webpack plugin
class MyPlugin {
apply(compiler) {
const hooks = ForkTsCheckerWebpackPlugin.getCompilerHooks(compiler);
// Async hook - can modify files and compilation
hooks.start.tapPromise('MyPlugin', async (change, compilation) => {
console.log('Type checking starting...');
console.log('Changed files:', change.changedFiles);
console.log('Deleted files:', change.deletedFiles);
// Can modify the change object
const modifiedChange = {
...change,
changedFiles: change.changedFiles?.filter(file => !file.includes('.test.'))
};
return [modifiedChange, compilation];
});
}
}Monitor type checking progress and provide user feedback.
// Progress reporting plugin
class TypeCheckProgressPlugin {
apply(compiler) {
const hooks = ForkTsCheckerWebpackPlugin.getCompilerHooks(compiler);
hooks.waiting.tap('TypeCheckProgressPlugin', (compilation) => {
console.log('β³ Type checking in progress...');
// Could integrate with webpack's ProgressPlugin
const logger = compilation.getLogger('TypeCheckProgressPlugin');
logger.info('TypeScript type checking is running');
});
}
}Handle type checking cancellation events.
class TypeCheckCancelPlugin {
apply(compiler) {
const hooks = ForkTsCheckerWebpackPlugin.getCompilerHooks(compiler);
hooks.canceled.tap('TypeCheckCancelPlugin', (compilation) => {
console.log('β Type checking was canceled');
// Cleanup or logging logic
const logger = compilation.getLogger('TypeCheckCancelPlugin');
logger.warn('Type checking process was canceled');
});
}
}Handle type checking errors and failures.
class TypeCheckErrorPlugin {
apply(compiler) {
const hooks = ForkTsCheckerWebpackPlugin.getCompilerHooks(compiler);
hooks.error.tap('TypeCheckErrorPlugin', (error, compilation) => {
console.error('π₯ Type checking error:', error);
// Send to error reporting service
if (process.env.NODE_ENV === 'production') {
this.reportError(error, compilation);
}
// Add compilation error
compilation.errors.push(new Error(`Type checking failed: ${error}`));
});
}
reportError(error, compilation) {
// Integration with error reporting services
// e.g., Sentry, Bugsnag, etc.
}
}Intercept and modify type checking issues.
class IssueFilterPlugin {
apply(compiler) {
const hooks = ForkTsCheckerWebpackPlugin.getCompilerHooks(compiler);
// Sync waterfall - can modify issues array
hooks.issues.tap('IssueFilterPlugin', (issues, compilation) => {
console.log(`π Found ${issues.length} type checking issues`);
// Filter issues based on custom logic
const filteredIssues = issues.filter(issue => {
// Example: Ignore issues in test files during development
if (process.env.NODE_ENV === 'development' && issue.file?.includes('.test.')) {
return false;
}
// Example: Convert specific warnings to errors
if (issue.code === 'TS7006' && process.env.STRICT_MODE === 'true') {
issue.severity = 'error';
}
return true;
});
// Log issue summary
const errors = filteredIssues.filter(i => i.severity === 'error').length;
const warnings = filteredIssues.filter(i => i.severity === 'warning').length;
console.log(`π Summary: ${errors} errors, ${warnings} warnings`);
return filteredIssues;
});
}
}Collect and report type checking statistics.
class TypeCheckStatsPlugin {
private stats = {
totalRuns: 0,
totalIssues: 0,
errorCount: 0,
warningCount: 0,
cancelCount: 0
};
apply(compiler) {
const hooks = ForkTsCheckerWebpackPlugin.getCompilerHooks(compiler);
hooks.start.tapPromise('TypeCheckStatsPlugin', async (change, compilation) => {
this.stats.totalRuns++;
return [change, compilation];
});
hooks.issues.tap('TypeCheckStatsPlugin', (issues) => {
this.stats.totalIssues += issues.length;
this.stats.errorCount += issues.filter(i => i.severity === 'error').length;
this.stats.warningCount += issues.filter(i => i.severity === 'warning').length;
return issues;
});
hooks.canceled.tap('TypeCheckStatsPlugin', () => {
this.stats.cancelCount++;
});
// Report stats on webpack done
compiler.hooks.done.tap('TypeCheckStatsPlugin', () => {
console.log('π Type Check Statistics:', this.stats);
});
}
}Save issues to file for external processing.
import fs from 'fs/promises';
class IssuePersistencePlugin {
constructor(private outputPath: string) {}
apply(compiler) {
const hooks = ForkTsCheckerWebpackPlugin.getCompilerHooks(compiler);
hooks.issues.tap('IssuePersistencePlugin', async (issues) => {
const issueData = {
timestamp: new Date().toISOString(),
issues: issues.map(issue => ({
severity: issue.severity,
code: issue.code,
message: issue.message,
file: issue.file,
location: issue.location
}))
};
try {
await fs.writeFile(this.outputPath, JSON.stringify(issueData, null, 2));
console.log(`πΎ Saved ${issues.length} issues to ${this.outputPath}`);
} catch (error) {
console.error('Failed to save issues:', error);
}
return issues;
});
}
}Hook integration with development servers and IDEs.
class DevToolsIntegrationPlugin {
apply(compiler) {
const hooks = ForkTsCheckerWebpackPlugin.getCompilerHooks(compiler);
hooks.issues.tap('DevToolsIntegrationPlugin', (issues) => {
// Send issues to development server for browser display
if (compiler.options.devServer) {
this.sendToBrowser(issues);
}
// Send to IDE via language server protocol
if (process.env.IDE_INTEGRATION) {
this.sendToIDE(issues);
}
return issues;
});
}
private sendToBrowser(issues: Issue[]) {
// WebSocket integration with dev server overlay
// Display issues in browser console or overlay
}
private sendToIDE(issues: Issue[]) {
// Language Server Protocol integration
// Send diagnostics to connected IDE
}
}Hooks automatically support webpack multi-compiler setups.
// The plugin automatically forwards hooks from child compilers to parent
const config = {
// Multi-compiler setup
mode: 'development',
entry: {
app: './src/app.ts',
worker: './src/worker.ts'
},
plugins: [
new ForkTsCheckerWebpackPlugin(),
new MyHookPlugin() // Will receive hooks from both compilers
]
};
class MyHookPlugin {
apply(compiler) {
// This will work for both single and multi-compiler setups
const hooks = ForkTsCheckerWebpackPlugin.getCompilerHooks(compiler);
hooks.issues.tap('MyHookPlugin', (issues) => {
// Handle issues from all child compilers
return issues;
});
}
}