Class vs. Property vs. Method/Accessor vs. Parameter decorators
There are some minor, but important differences between the various decorator types, which you must know if you want to use them (but don’t worry, you can always look this information up online, or locally in the type definitions). They mainly differ in the parameters passed into the decorator. For example a class decorator only has access to the given class (the target), while a property decorator also has access to the property key.
To get a quick glance of the 4 different decorator types, I have created this little snippet:
```ts
@classDecorator
class Test {
@propertyDecorator
private _property: string = "";
@methodDecorator
public method(@parameterDecorator parameter: string) {
console.log(`${this._property} ${parameter} World!`);
}
@methodDecorator // method decorator can be applied to accessor
set property(value: string) {
this._property = value;
}
}
```
If you are interested in the exact types of them, I have listed them here as well, but as I already mentioned you can always look them up in your local type definitions.
```ts
// Types form the official TypeScript library (https://github.com/microsoft/TypeScript/blob/912c01a2a69fdba4a30e508048f8b18517e90f04/lib/lib.es5.d.ts#L1426-L1429)
// Every decorator needs to be assignable to one of those 4 types
type ClassDecorator = <T extends Function>(target: T) => T | 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;
const methodDecorator: MethodDecorator = (target, propertyKey, descriptor) => {
// target = if static method: constructor of applied class
// if instance method: prototype of applied class
// propertyKey = name of the method
// descriptor = metadata of member (value, accessors, enumerable, ...)
return descriptor;
};
const propertyDecorator: PropertyDecorator = (target, propertyKey) => {
// target = if static property: constructor of applied property,
// if instance property: prototype of applied property
// propertyKey = name of the property
};
const classDecorator: ClassDecorator = (target) => {
// target = if static property: constructor of applied property,
};
const parameterDecorator: ParameterDecorator = (
target,
propertyKey,
parameterIndex
) => {
// target = if static method: constructor of applied method parameter,
// if instance method: prototype of applied method parameter
// propertyKey = name of the method parameter
// parameterIndex = ordinal index of the parameter in the arguments list
};
```