Decorators are functions that are invoked with a prefixed
@ symbol, and immediately followed by a
class, parameter, method or property. The decorator function is supplied information about the
class, parameter or method, and the decorator function returns something in its place, or manipulates its target in some way. Typically the "something" a decorator returns is the same thing that was passed in, but it has been augmented in some way.
Decorators are quite new in TypeScript, and most use cases demonstrate the use of existing decorators. However, decorators are just functions, and are easier to reason about after walking through a few examples.
Decorators are functions, and there are four things (
class, parameter, method and property) that can be decorated; consequently there are four different function signatures for decorators:
declare type ClassDecorator = <TFunction extends Function>(target: TFunction) => TFunction | void;
declare type PropertyDecorator = (target: Object, propertyKey: string | symbol) => void;
declare type MethodDecorator = <T>(target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>) => TypedPropertyDescriptor<T> | void;
declare type ParameterDecorator = (target: Object, propertyKey: string | symbol, parameterIndex: number) => void;
Readers who have played with Angular will notice that these signatures do not look like the signatures used by Angular specific decorators like
@Component. This means that the
@Component(). In turn, this means that there must be a
Component function somewhere that returns a function matching one of the decorator signatures outlined above. This is an example of the decorator factory pattern.
If decorators still look confusing, perhaps some examples will clear things up.