How to Use Decorators in TypeScript
Use decorators in TypeScript when classes, methods, properties, or parameters need metadata, automatic behavior, or reusable cross-cutting logic. They are common in frameworks like :contentReference[oaicite:0]{index=0}, :contentReference[oaicite:1]{index=1}, and :contentReference[oaicite:2]{index=2}.
What you’ll build or solve
You’ll learn how to use decorators in TypeScript with class and method decorators. You’ll also know when decorators are better than manual repetitive logic.
Learn TypeScript on Mimo
When this approach works best
This approach is the right choice when behavior should be attached declaratively to existing classes or methods.
Common real-world scenarios include:
- Route handlers
- Validation metadata
- ORM entities
- Logging wrappers
- Dependency injection
This is a bad idea when the same result is clearer with a plain function wrapper.
Prerequisites
You only need:
- Advanced TypeScript basics
- Classes and methods
experimentalDecoratorsenabled intsconfig.json
Step-by-step instructions
Step 1: Enable decorators in TypeScript config
Decorators require compiler support.
JSON
{
"compilerOptions": {
"experimentalDecorators": true
}
}
Without this, decorator syntax will fail.
Step 2: Create a class decorator
A decorator is a function that receives the class.
function Logger(target: Function): void {
console.log(`Registered: ${target.name}`);
}
@Logger
class UserService {}
This runs when the class is defined.
It is useful for metadata registration.
Step 3: Create a method decorator
Method decorators can wrap behavior.
function LogCall(
target: object,
key: string,
descriptor: PropertyDescriptor
): void {
const original = descriptor.value;
descriptor.value = function (...args: unknown[]) {
console.log(`Calling ${key}`);
return original.apply(this, args);
};
}
Apply it to a method.
class PaymentService {
@LogCall
charge(): void {
console.log("Charged");
}
}
This keeps reusable wrappers clean.
What to look for:
- Decorators add metadata or behavior
- Enable
experimentalDecorators - Great for frameworks and DI
- Method decorators can wrap logic
- Use sparingly for clarity
Examples you can copy
Logging decorator
@Logger
class ApiService {}
Method wrapper
@LogCall
save()
Framework route
@Get("/users")
Common mistakes and how to fix them
Mistake 1: Forgetting compiler support
What the reader might do:
Use @Logger without config.
Why it breaks: TypeScript rejects decorator syntax.
Corrected approach:
Enable experimentalDecorators.
Mistake 2: Overusing decorators for simple helpers
What the reader might do:
Decorate tiny utility methods.
Why it breaks: indirection hurts readability.
Corrected approach:
Use plain wrappers when simpler.
Mistake 3: Mutating descriptors incorrectly
What the reader might do:
Replace the method without preserving this.
Why it breaks: instance methods lose context.
Corrected approach:
Use original.apply(this, args).
Troubleshooting
If syntax errors appear, enable decorators in tsconfig.json.
If methods lose context, preserve this.
If logic feels hidden, prefer plain functions.
If using frameworks, follow their decorator conventions.
Quick recap
- Decorators attach reusable behavior declaratively
- Enable
experimentalDecorators - Great for frameworks and metadata
- Preserve
thisin method wrappers - Prefer simpler patterns when possible
Join 35M+ people learning for free on Mimo
4.8 out of 5 across 1M+ reviews
Check us out on Apple AppStore, Google Play Store, and Trustpilot