TypeScript微服务信号处理报TS2769:string类型不兼容Signals
Hey there, let's break down why this error started popping up and how to fix it properly.
Why the Error Happens Now (But Didn't Before)
This issue comes down to stricter type checking—either from an upgrade to your TypeScript version or the @types/node type definitions. Here's the key breakdown:
- Your
signalsenum is a numeric enum, which TypeScript automatically reverse-maps. That meansObject.values(signals)returns an array with both numeric codes (like1,2) and string keys (like"SIGHUP","SIGINT"), making the type(string | signals)[]. - The
process.on()method expects its first argument to be of typeNodeJS.Signals—a union of specific string literals (e.g.,"SIGHUP","SIGINT"). Previously, TypeScript might have allowed loose string assignments, but now it enforces that you only pass exact signal name literals, hence the TS2769 error.
Fixes to Resolve the TS2769 Error
Fix 1: Use Enum Keys Instead of Values (Recommended)
Since process.on() works best with human-readable signal names (strings) rather than numeric codes, iterate over the enum's keys instead of values. This ensures you pass valid, type-safe signal names:
enum signals { SIGHUP = 1, SIGINT = 2, SIGTERM = 15 } const shutdown = (signal: string, value: number) => { logger.warn("shutdown!"); Db.closeAll(); process.exit(value); }; // Iterate over enum keys (signal names) instead of mixed values/keys Object.keys(signals).forEach((signal) => { // Assert the signal is a valid NodeJS.Signals type to satisfy TypeScript process.on(signal as NodeJS.Signals, () => { logger.warn(`process received a ${signal} signal`); // Assert the signal is a key of our enum to safely access its numeric value shutdown(signal, signals[signal as keyof typeof signals]); }); });
Fix 2: Filter Numeric Values from Object.values()
If you prefer sticking with Object.values(), filter out the string elements to only pass numeric signal codes (Node.js does accept numeric codes, though names are more readable):
enum signals { SIGHUP = 1, SIGINT = 2, SIGTERM = 15 } const shutdown = (signal: number, value: number) => { logger.warn("shutdown!"); Db.closeAll(); process.exit(value); }; // Filter out string entries to keep only numeric signal codes (Object.values(signals) as number[]).forEach((signal) => { process.on(signal, () => { logger.warn(`process received a ${signal} signal`); shutdown(signal, signal); }); });
Fix 3: Use Built-in NodeJS.Signals Type
Skip defining your own enum entirely and leverage the pre-defined NodeJS.Signals type from @types/node for maximum type safety:
// Use the built-in signal type instead of a custom enum const signals: NodeJS.Signals[] = ['SIGHUP', 'SIGINT', 'SIGTERM']; const shutdown = (signal: NodeJS.Signals, exitCode: number) => { logger.warn("shutdown!"); Db.closeAll(); process.exit(exitCode); }; signals.forEach((signal) => { process.on(signal, () => { logger.warn(`process received a ${signal} signal`); // Map signal names to exit codes as needed const exitCode = signal === 'SIGHUP' ? 1 : signal === 'SIGINT' ? 2 : 15; shutdown(signal, exitCode); }); });
内容的提问来源于stack exchange,提问作者M A SIDDIQUI

