Сейчас я изучаю декораторы Typescript. Моя первая цель - немного воспроизвести то, что @ Slf4J из Project Lombok делает в Java, в Typescript. Идея состоит в том, чтобы аннотировать / украшать класс, например, @logger, чтобы получить поле log типа LogUtil внутри этого же класса, чтобы вызвать, например, log.info ().
LogUtil class :
export class LoggerUtil {
logLevel: LogLevel;
constructor(logLevel: LogLevel) {
this.logLevel = logLevel;
}
error(className: string, message: string) {
if (this.logLevel >= LogLevel.ERROR) {
console.error(`${new Date()} [ERROR] ${className}: ${message}`);
}
}
warn(className: string, message: string) {
if (this.logLevel >= LogLevel.WARN) {
console.log(`${new Date()} [WARN] ${className}: ${message}`);
}
}
log(className: string, message: string): void {
console.log(`${new Date()} [LOG] ${className} ${message}`)
}
info(className: string, message: string): void {
if (this.logLevel >= LogLevel.INFO) {
console.log(`${new Date()} [INFO] ${className}: ${message}`)
}
}
call(className: string, message: string) {
if (this.logLevel >= LogLevel.INFO) {
console.log(`${new Date()} [CALL] ${className}.${message}`)
}
}
debug(className: string, message: string) {
if (this.logLevel >= LogLevel.DEBUG) {
console.log(`${new Date()} [DEBUG] ${className}: ${message}`)
}
}
}
Перечисление LogLevel:
export enum LogLevel {
ERROR = 0,
WARN = 1,
INFO = 2,
DEBUG = 3
}
Пример класса с использованием декоратора @logger для получения экземпляра LoggerUtil в качестве журнала
@logger
export class SomeService {
exampleFunction() {
log.info("exampleFunction called")
}
}
Я сейчас пытаюсь сделать это с декораторами уровня класса. Здесь я пытаюсь делать разные вещи:
Использование API Reflect для определения свойства класса. Здесь я даже не уверен, работает ли это вообще.
export function logger() {
return function(target: Function) {
Reflect.defineProperty(target, "log", { value: new LoggerUtil(LogLevel.DEBUG) } )
}
}
Использование прототипа класса для определения свойства:
export function logger() {
return function(target: Function) {
target.prototype.log = new LoggerUtil(LogLevel.DEBUG);
}
}
При каждом подходе я получаю журнал «Не удается найти имя» '"при обращении к экземпляру журнала в Сервисе:
@logger
export class SomeService {
exampleFunction() {
log.info("exampleFunction called") // Cannot find name 'log'
}
}
Возможна ли вообще моя идея? Есть что-то фундаментальное, чего мне не хватает?
Большое спасибо за любые отзывы!