Как читать дженерики в TypeScript?

Всем привет!
Есть следующий код:

function loggingClassDecorator(url: string) {
  return function <T extends { new (...args: any[]): {} }>(constructor: T) {
    return class extends constructor {
      isUrgent: boolean = false
      constructor(...args: any[]) {
        super(...args)
        console.log('Log: new instance of class ' + constructor.name)
        console.log('Reporting URL: ' + url)
      }
    }
  }
}

@loggingClassDecorator('https://example.com/needs-dark-mode')
class BugReport {
  type: string = 'report'
  constructor(public title: string) {}
}
 
const bug = new BugReport('Needs dark mode')
console.log(bug.title) // Needs dark mode
console.log(bug.type) // report


Подскажите, как правильно читать следующую строчку?
function <T extends { new (...args: any[]): {} }>(constructor: T)


Я читаю её следующим образом:
{ new (...args: any[]): {} } — это сигнатура класса, чей конструктор принимает произвольное кол-во аргументов и возвращает инстанс (объект)

Соответственно, мы имеем дело с функцией, которая в качестве аргумента принимает конструктор класса (функцию-конструктор), этот конструктор должен быть типа Т, т.е. быть любым произвольным классом.

Если не так, поправьте, пожалуйста.
Не совсем понимаю, зачем здесь квадратные скобки.

Спасибо!
  • Вопрос задан
  • 104 просмотра
Решения вопроса 1
bingo347
@bingo347 Куратор тега TypeScript
Crazy on performance...
Данная функция принимает аргумент constructor любого типа T, который является подтипом типа { new (...args: any[]): {} }

В свою очередь { new (...args: any[]): {} } - это абсолютно тоже самое, что и new (...args: any[]) => {}. Это сигнатура конструктора, с любым количеством любых элементов и инстанциирующий значение с типом {}.

Ну и тип {} - это множество всех не нулевых значений (не только объектов), то есть по сути это как тип any, но без null | undefined и с не сломанной вариантностью. Здесь его безболезненно можно заменить на тип unknown, в отличии от тех же аргументов, где из-за контрвариантности аргументов функций (и конструкторов) предикаты на типах ломаются и без any нормально не сделать.

В целом, под такой дженерик подойдет абсолютно любой конструктор
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
Aetae
@Aetae Куратор тега TypeScript
Тлен
Всё правильно. Квадратные скобки чтоб обозначить, что args - массив, в случае с any их можно выкинуть.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы