Pull to refresh

Comments 6

А ещё можно эти столбики декораторов сжимать, если там повторяющиеся общие паттерны действий у методов.

Например такой код:

    @GetArrayWithCache('symbol/:id')
    @InfluxTimeLog()
    async getSymbol(@Headers() headers: object, @Param('id') id: string): TProxyItem {
        return this.symbolsService.getById(id);
    }

может иметь такой вот составной декоратор

export function GetArrayWithCache(path: string) {
    return applyDecorators(
        Get(path),
        ApiOkResponse(ARRAY_RESPONSE_DOC),
        ApiOperation(ARRAY_CACHE_DOC),
        CheckNotFound(),
    );
}

где applyDecorators это функция-склеиватель

export function applyDecorators(
  ...decorators: Array<ClassDecorator | MethodDecorator | PropertyDecorator>
) {
    return <TFunction extends Function, Y>(
      target: TFunction | object,
      propertyKey?: string | symbol,
      descriptor?: TypedPropertyDescriptor<Y>,
    ) => {
        for (const decorator of decorators) {
            if (target instanceof Function && !descriptor) {
                (decorator as ClassDecorator)(target);
                continue;
            }
            (decorator as MethodDecorator | PropertyDecorator)(
                target,
                propertyKey,
                descriptor,
            );
        }
    };
}

И, как видите, в составном декораторе можно передать параметры... в том числе и другие декораторы, если это нужно.

А ещё декораторами можно описывать апи и в итоге вместо писанины ручной валидации или конфигов или каких-либо других хитросплетений - мы можем просто сделать так

export class AccountListArgs {
    @Property({
        enum: EFieldsSortingAccounts,
        description: 'orderBy',
    })
    @IsOptional()
    @IsEnum(EFieldsSortingAccounts)
    orderBy?: EFieldsSortingAccounts = EFieldsSortingAccounts.ID;
}

и, натравив туда пакеты class-transformer и class-validator с ходу отвалидировать на тип, енум, не обязательность наличия и ещё сверху сгенерировать swagger-схему и на лету её показать на отдельном урле с документацией.

В общем, если вы ещё не используете декораторы - время пришло.

В общем, если вы ещё не используете декораторы - время пришло.

На самом деле если вы ещё не используете TS декораторы – то сейчас самый неподходящий момент для начала их использования. Во-первых, core team разработчики TS называют декораторы одним из самых неудачных экспериментов (не зря они experimentalDecorators). Во-вторых, как причина первого пункта, в ECMAScript на подходе нативные декораторы, которые имеют такой же синтаксис, но работают совершенно иначе. И как этот зоопарк дружить друг с другом пока что под большим вопросом.

Они удобные, это да. Но лично я сейчас предпочитаю императивный подход тогда, когда это уместно.

Ну, неудачный это эксперимент или нет, но это удобно, это работает, на этом множество фреймворков построено и кода написано. На столько что где-то это корпоративный легаси уже. И фатальных недостатков так то нет. Кроме того что обогнало оригинальный JS на несколько лет и теперь придется чуть поиграть с транспилерами.

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

Если к члену класса прикреплены несколько декораторов, их выполнение происходит сверху вниз по очереди.

хмм, в моей шпаргалке записано так:
Если декораторы записываются в столбик, то вызываются они снизу вверх (при этом предварительное вычисление идёт сверху вниз)

Я сейчас только пытаюсь понять, с чем это едят, но у меня сложилось мнение, что

@dec1
@dec2
@dec3

Считается как

dec1(dec2(dec3()))

С одной стороны, функции вызываются сверху вниз, но если смотреть, чьё значение посчитается первым, то снизу вверх. Или я неправильно интерпретирую понятие выполнения функции, что вполне может быть.

Sign up to leave a comment.

Articles