I am working on a node application and using Typescript. I have winston 3. In my code I have added custom log levels;
const myCustomLevels = {
levels: {
data: 10,
protocol: 9,
debug: 8,
info: 7,
notice: 6,
note: 5,
warn: 4,
error: 3,
crit: 2,
alert: 1,
emerg: 0,
}
}
then
const logger = winston.createLogger({
level: data,
levels: myCustomLevels.levels,
format: winston.format.combine(
winston.format.json()
),
transports: [new winston.transports.Console()],
});
The problem I need help with is when I use the logger Typescript complains.
logger.protocol({});
in this case the types are const logger: winston.Logger
and the ts says [ts] Property 'protocol' does not exist on type 'Logger'. [2339]
.
Typescript doesn't know about my levels.
How do I correct this so that tsc
knows about my levels on the logger?
The definitions as currently written do not unfortunately allow for custom log levels. The simplest solution is to cast the returned logger to a logger and an intersection with a type that contains the extra methods. We can create this type based on your const declaration using the mapped type Record
and keyof
import * as winston from 'winston'
const logger = winston.createLogger({
level: data,
levels: myCustomLevels.levels,
format: winston.format.combine(
winston.format.json()
),
transports: [new winston.transports.Console()],
}) as winston.Logger & Record<keyof typeof myCustomLevels['levels'], winston.LeveledLogMethod>;
logger.protocol({})
Note I toyed around with augmenting the existing module definition but because createLogger
is declared as a variable with an inline function signature we can't really extend it with augmentation.
If this a general problem for you, you could write a general function that preserves the levels:
function createWinstonLogger<T>(options?: Pick<winston.LoggerOptions, Exclude<keyof winston.LoggerOptions, 'levels'>> & { levels: T }) {
return winston.createLogger(options) as winston.Logger & Record<keyof T, winston.LeveledLogMethod>
}
const logger = createWinstonLogger({
level: data,
levels: myCustomLevels.levels,
format: winston.format.combine(
winston.format.json()
),
transports: [new winston.transports.Console()],
});
logger.protocol({})