What are TypeScript Decorators?
A TypeScript decorator is a design pattern that allows for the annotation and modification of classes or their members (methods, properties, or parameters) at design time.
Decorators are functions that are prefixed with the @
symbol and can be used to extend or alter the behavior of the class or member they are attached to, enabling meta-programming techniques such as aspect-oriented programming.
Decorators provide a way to add both annotations and a meta-programming syntax for class declarations and members, leveraging JavaScript's ability to modify runtime code behavior through functions that are called at design time during the class or member evaluation process.
In TypeScript, decorators provide a way to add both annotations and a meta-programming syntax for class declarations and members.
Note: This guide covers experimental stage 2 decorators. For information on Stage 3 decorators see decorators in TypeScript 5.0.
Enabling decorator support in TypeScript
Before you start using decorators, you must enable them in your TypeScript configuration. To do this set the experimentalDecorators
compiler option to true in your tsconfig.json
file:
{"compilerOptions": {"target": "ES5","experimentalDecorators": true}}
Types of decorators
TypeScript supports several types of decorators:
- Class decorators
- Method decorators
- Accessor decorators
- Property decorators
- Parameter decorators
Class decorators
A class decorator is declared just before a class declaration. It is applied to the constructor of the class and can be used to observe, modify, or replace a class definition.
function sealed(constructor: Function) {Object.seal(constructor)Object.seal(constructor.prototype)}@sealedclass Greeter {greeting: stringconstructor(message: string) {this.greeting = message}greet() {return 'Hello, ' + this.greeting}}
In this example, the @sealed
decorator will seal both the constructor and its prototype, preventing new properties from being added to them.
Method decorators
A method decorator is applied to the property descriptor of the method, and can be used to observe, modify, or replace a method definition.
function enumerable(value: boolean) {return function (target: any,propertyKey: string,descriptor: PropertyDescriptor) {descriptor.enumerable = value}}class Greeter {greeting: stringconstructor(message: string) {this.greeting = message}@enumerable(false)greet() {return 'Hello, ' + this.greeting}}
This @enumerable
decorator modifies the enumerable
property of the greet
method descriptor, controlling its visibility during enumeration.
Accessor decorators
Accessor decorators are applied to the property descriptors for the accessor and can be used similarly to method decorators.
function configurable(value: boolean) {return function (target: any,propertyKey: string,descriptor: PropertyDescriptor) {descriptor.configurable = value}}class Greeter {private _greeting: stringconstructor(message: string) {this._greeting = message}@configurable(false)get greeting() {return this._greeting}set greeting(value: string) {this._greeting = value}}
Here, the @configurable
decorator makes the greeting
accessor non-configurable, meaning it cannot be deleted or changed.
Property decorators
Property decorators are used to observe, modify, or replace properties in a class.
function format(formatString: string) {return function (target: any, propertyKey: string) {// property decorator logic here}}class Greeter {@format('Hello, %s')greeting: stringconstructor(message: string) {this.greeting = message}}
The @format
decorator in this case could be used to format the greeting
property, though the implementation details are not shown.
Parameter decorators
Parameter decorators are declared before a parameter declaration and are applied to the function for a class constructor or method declaration.
function required(target: Object,propertyKey: string | symbol,parameterIndex: number) {// parameter decorator logic here}class Greeter {greet(@required name: string) {return 'Hello, ' + name}}
The @required
decorator can be used to ensure that a parameter is provided when the method is called.
For further reading on TypeScript decorators see the official documentation.