Декораторы TypeScript, получение типов аргументов конструктора и внедрение

Предположим, у вас есть такой класс с прикрепленным к нему декоратором Router.

@Router
class AuthRouter {

    constructor(private cacheService: CacheService) {}
}

Как получить типы параметров конструктора из декоратора Router? Предположим, мы сохранили синглтон CacheService, к которому мы можем получить доступ, если знаем имя класса «CacheService».

function Router(target) {

    // somehow get the constructor class name
    const dependencyNames = 'CacheService' // an array if multiple args in constructor

    // getSingleton is a function that will retrieve
    // a singleton of the requested class / object
    return new target(getSingleton(dependencyNames))
}

Поэтому всякий раз, когда мы используем AuthRouter, в него уже будет введено CacheService.


person borislemke    schedule 18.04.2017    source источник
comment
Это будет работать с другими языками, такими как C #, с использованием Reflection, что позволяет получить доступ ко всем типам во время выполнения. Но TypeScript отличается. Он не включает информацию о типах во время выполнения, поэтому типы не могут использоваться во время него. Решение, которое вы можете попробовать, это RegExping target.toString() для имен аргументов, а затем выполнить одноэлементную инъекцию.   -  person Jevgeni    schedule 18.04.2017
comment
Взгляните на пример декоратора параметров, они что-то делают вот так, но я не уверен, что это сработает с конструктором. Но кажется, что вы упускаете смысл декораторов классов. Он не должен возвращать экземпляр класса, если вы вернетесь, то это должна быть функция-конструктор.   -  person Nitzan Tomer    schedule 18.04.2017
comment
@NitzanTomer Я понимаю, я просто возился с декораторами, чтобы понять, как они работают. Мне было интересно, как Angular делает это внутри. Является ли возврат нового конструктора просто принципом проектирования Decorators или он будет иметь негативные побочные эффекты?   -  person borislemke    schedule 18.04.2017
comment
@jevgenig Я надеялся, что это будет возможно с помощью библиотеки reflect-metadata.   -  person borislemke    schedule 18.04.2017
comment
Я не уверен, что понимаю, о чем вы спрашиваете. Вы можете не возвращать ничего из функции декоратора, но если вы это сделаете, это должна быть функция конструктора. Какие негативные побочные эффекты?   -  person Nitzan Tomer    schedule 18.04.2017
comment
@NitzanTomer я спрашиваю, действительно ли мы должны возвращать constructor класса, или это просто предлагается концепцией Decorator в целом (также в python)? Дело в том, что приведенный выше код работает как задумано, даже если я возвращаю экземпляр класса вместо нового конструктора.   -  person borislemke    schedule 18.04.2017
comment
Декоратор класса будет вызываться только один раз для каждого украшенного класса. Он не будет вызываться каждый раз при вызове new AuthRouter(). Я сомневаюсь, что ваш код действительно работает так, как вы задумали.   -  person Nitzan Tomer    schedule 18.04.2017
comment
@NitzanTomer Я не создаю новый экземпляр каждый раз, в моем примере вместо того, чтобы делать что-то вроде router.use('/auth', new AuthRouter()), я просто делаю router.use('/auth', <any>AuthRouter) ‹- обратите внимание, что я не повторно создаю экземпляр украшенного класса. Спасибо за помощь, я решил не идти по этому пути и нашел что-то более привлекательное с декораторами   -  person borislemke    schedule 18.04.2017
comment
Если вы используете --emitDecoratorMetadata, вы можете использовать Reflect API для доступа к примерному списку типов параметров. Однако на самом деле они не являются типами, и вам следует с осторожностью полагаться на этот механизм.   -  person Aluan Haddad    schedule 23.04.2017


Ответы (1)


import 'reflect-metadata'

function Router(target) {
    const types = Reflect.getMetadata('design:paramtypes', target);
    // return a modified constructor
}

Обратите внимание, что вы вызываете getMetadata без третьего параметра. types будет массивом параметров конструктора. types[0].name === 'CacheService' в вашем случае.

person HandyManDan    schedule 24.10.2018