- Abstraction
- AI Pair Programming
- Algorithm
- API
- Array
- Array methods
- Booleans
- Callback
- Class
- Class Members
- Closure
- Closure
- Code refactoring
- Comment
- Computer programming
- Conditional statements
- Constant
- Constructor
- Coupling and Cohesion
- Data types
- Debugging
- Decorator
- Dependency
- Destructuring
- Dictionary
- Enum
- Event
- Exception / Error handling
- Function
- Generic / Template
- Higher-order function
- IDE
- Immutability
- Inheritance
- Input validation
- Integer
- Interface
- Iteration patterns
- Legacy code
- Loop
- Machine learning
- Memoization
- Memory and references
- Method
- Module
- Null / Undefined / None
- Null safety / Optional values
- Object
- Object-Oriented Programming (OOP)
- Operator
- Parameter
- Parsing
- Promise and Async/Await
- Prompt Engineering
- Recursion
- Regular expression
- Return statement
- Rollback
- Runtime
- Scope
- Script
- Sequence
- Set
- Spaghetti code
- Spread and Rest operators
- State management
- String
- Switch statement
- Synchronous vs Asynchronous execution
- Syntax
- Technical debt
- Ternary operator
- Testing
- This / Self
- Tuple
- Type casting
- Type conversion
- Variable
- Vibe coding
- Webhook
PROGRAMMING-CONCEPTS
Decorator: Definition, Purpose, and Examples
A decorator is a programming feature that lets you wrap a function, method, or class with extra behavior without modifying its original code. It’s a way to enhance or extend functionality in a clean, reusable style.
Python and TypeScript both support decorators directly, and JavaScript supports them through the modern ECMAScript proposal. Decorators often appear in frameworks, logging systems, validation tools, and meta-programming utilities.
Think of a decorator as placing a helpful “attachment” on top of an existing feature — similar to putting a protective case on your phone. The phone remains the same, but it gains something additional.
Why Decorators Exist
Decorators help developers:
- avoid repeating the same setup code
- add cross-cutting features (logging, caching, authorization)
- separate concerns cleanly
- modify behavior dynamically
- keep the original function easy to read
They are especially useful when the same enhancement appears across many functions or classes.
Decorators in Python
Python’s decorator syntax uses the @ symbol placed directly above a function or method. The decorator receives the original function as input and returns a wrapped version.
A Simple Python Decorator
Python
def announce(func):
def wrapper(*args, **kwargs):
print("Starting operation...")
result = func(*args, **kwargs)
print("Finished.")
return result
return wrapper
Here, wrapper adds extra behavior before and after the original func.
Applying it:
Python
@announce
def compute():
return 20 * 3
compute()
This prints messages before and after running compute().
The original function doesn’t know anything about these additions — the decorator handles it all.
Decorators for Performance Timing
Python
import time
def timer(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
total = time.time() - start
print(f"Took {total:.4f} seconds")
return result
return wrapper
Apply to any function you want to measure.
This is common in data analysis, where performance varies by dataset size.
Decorators with Arguments (Decorator Factories)
Sometimes you want to configure the decorator itself.
Python
def repeat(times):
def decorate(func):
def wrapper(*args, **kwargs):
for _ in range(times):
func(*args, **kwargs)
return wrapper
return decorate
Using it:
Python
@repeat(3)
def ping():
print("ping")
This calls ping() three times.
Decorator factories give you flexible, parameter-driven behavior.
Decorators in TypeScript and Modern JavaScript
TypeScript supports decorators for:
- classes
- methods
- accessors
- properties
- parameters
JavaScript is adopting similar features through the TC39 decorators proposal.
Class Decorator Example (TypeScript)
function locked(constructor: Function) {
Object.seal(constructor);
Object.seal(constructor.prototype);
}
@locked
class Vault {
level = 5;
}
The decorator prevents extensions to the class and its prototype.
This is a simple example of modifying metadata and behavior at the class level.
Method Decorator Example (TypeScript)
function log(_target: any, property: string, descriptor: PropertyDescriptor) {
const original = descriptor.value;
descriptor.value = function (...args: any[]) {
console.log(`Calling ${property} with`, args);
return original.apply(this, args);
};
}
class Calculator {
@log
multiply(a: number, b: number) {
return a * b;
}
}
The decorator intercepts calls to .multiply() and logs the arguments.
This is one of the most common real-world patterns for decorators in TypeScript.
Accessor Decorator Example
function minValue(limit: number) {
return function (
_target: any,
_prop: string,
descriptor: PropertyDescriptor
) {
const original = descriptor.set!;
descriptor.set = function (value: number) {
if (value < limit) {
throw new Error(`Value must be >= ${limit}`);
}
original.call(this, value);
};
};
}
class Settings {
private _refresh = 30;
@minValue(10)
set refresh(value: number) {
this._refresh = value;
}
}
This decorator enforces a rule on any assignment to the property.
It centralizes validation logic instead of repeating it.
Decorator-Like Patterns in Swift
Swift does not have a decorator keyword, but it supports similar behavior through property wrappers and function composition.
Property Wrapper Example
@propertyWrapper
struct NonEmpty {
private var value: String = ""
var wrappedValue: String {
get { value }
set { value = newValue.isEmpty ? value : newValue }
}
}
struct FormField {
@NonEmpty var name: String
}
Property wrappers behave very similarly to decorators on stored properties.
They modify how the value is stored and retrieved without changing the external API.
Real-World Uses of Decorators
Below are fresh, practical scenarios that safely illustrate the power of decorators.
Example 1: Authorization Check (Python)
Python
def require_admin(func):
def wrapper(user, *args, **kwargs):
if not user.get("admin"):
raise PermissionError("Admin privileges required.")
return func(user, *args, **kwargs)
return wrapper
This pattern appears in APIs, CLI tools, and dashboards.
It separates authorization from business logic.
Example 2: Caching Repeated Results (Python)
Python
def cache(func):
stored = {}
def wrapper(x):
if x not in stored:
stored[x] = func(x)
return stored[x]
return wrapper
Any expensive calculation wrapped with @cache becomes far more efficient.
Example 3: Logging in TypeScript Services
function track(target: any, key: string, descriptor: PropertyDescriptor) {
const original = descriptor.value;
descriptor.value = function (...args: any[]) {
console.log(`→ ${key}`, args);
return original.apply(this, args);
};
}
In API services or data pipelines, decorators are used to:
- track requests
- log transformations
- validate parameters
- wrap asynchronous operations
Why Developers Use Decorators
Decorators shine in situations where you want to apply the same enhancement to multiple features without scattering boilerplate everywhere.
They are ideal for:
- logging
- performance timing
- input validation
- caching
- rate limiting
- authorization
- dependency injection
- property validation
- metadata tagging
Instead of repeating the same code 10 times, you place a decorator once and apply it where needed.
Common Mistakes
Forgetting to Preserve Function Metadata (Python)
Naive wrappers hide the original function’s name or docstring.
Using functools.wraps solves this neatly.
Overusing Decorators
They can make code hard to read if every function has multiple layers of indirection.
Confusing Decorator Order
In both Python and TypeScript, the order of decorators matters.
The outermost one applies first.
Using Decorators for Simple Tasks
Sometimes a normal helper function is clearer.
Summary
Decorators allow you to enhance classes, functions, and properties without modifying their core logic. Python uses @decorator syntax, TypeScript supports class and method decorators, and Swift mirrors much of this through property wrappers. Decorators help reduce repetitive code, keep logic clean, and handle cross-cutting concerns like logging, caching, and validation. They are a key tool for building elegant, maintainable code in modern programming.
Sign up or download Mimo from the App Store or Google Play to enhance your programming skills and prepare for a career in tech.