Syntax
@decoratorName
class Name { }Examples
A Basic Class Decorator
A decorator that logs class instantiation.
function logged(target: Function) {
console.log(`Class defined: ${target.name}`);
}
@logged
class UserService {
constructor() {
console.log("UserService created");
}
}
new UserService();
// "Class defined: UserService" logs once, at class definition timeA Method Decorator
Wrapping a method to add behavior, like timing its execution.
function measure(target: any, context: ClassMethodDecoratorContext) {
return function (this: any, ...args: any[]) {
const start = performance.now();
const result = target.apply(this, args);
console.log(`${String(context.name)} took ${performance.now() - start}ms`);
return result;
};
}
class Calculator {
@measure
compute(n: number): number {
return n * n;
}
}Best practices
- Decorators are a stable, standard TypeScript feature as of the TC39 Stage 3 support landing in TypeScript 5.9 - no experimental flag is needed for the standard syntax
- Reach for decorators when building framework-level, cross-cutting functionality like dependency injection, validation, or logging - not as a general-purpose everyday tool
- Keep individual decorators focused on a single responsibility, similar to good middleware design
- When adopting a framework like Angular or NestJS, follow that framework's specific decorator conventions and configuration requirements closely, since they may build on this feature in framework-specific ways
At a glance
- Purpose
- Static types for JavaScript
- File extension
- .ts ยท .tsx
- Runs in
- Compiled to JavaScript
- Usually used with
- JavaScript and its ecosystem
Specifications & further reading
Related TypeScript documentation
Typed Classes
TypeScript enhances JavaScript classes with typed properties, constructor parameters, and method signatures. Class fields must either be initialized or explicitly typed, and TypeScript checks that constructor assignments match declared property types, catching mismatches before runtime.Access Modifiers: public, private, protected
Access modifiers control visibility of class members. public (the default) is accessible from anywhere. private restricts access to within the declaring class only, not even subclasses. protected allows access within the class and its subclasses, but not from outside. These are compile-time only checks - true runtime privacy needs the # syntax instead.Abstract Classes
An abstract class cannot be instantiated directly - it exists only to be extended. It can define abstract methods (a signature with no implementation, which subclasses must provide) alongside regular, fully-implemented methods that subclasses inherit as-is. This is TypeScript's way of enforcing a shared contract across a family of related classes.implements Keyword
The implements keyword declares that a class must conform to a specific interface's shape - TypeScript checks that every property and method the interface requires is actually present with a compatible type. Unlike extends, implements does not provide any inherited implementation; it is purely a compile-time contract check.
TypeScript enhances JavaScript classes with typed properties, constructor parameters, and method signatures. Class fields must either be initialized or explicitly typed, and TypeScript checks that constructor assignments match declared property types, catching mismatches before runtime.Access Modifiers: public, private, protected
Access modifiers control visibility of class members. public (the default) is accessible from anywhere. private restricts access to within the declaring class only, not even subclasses. protected allows access within the class and its subclasses, but not from outside. These are compile-time only checks - true runtime privacy needs the # syntax instead.Abstract Classes
An abstract class cannot be instantiated directly - it exists only to be extended. It can define abstract methods (a signature with no implementation, which subclasses must provide) alongside regular, fully-implemented methods that subclasses inherit as-is. This is TypeScript's way of enforcing a shared contract across a family of related classes.implements Keyword
The implements keyword declares that a class must conform to a specific interface's shape - TypeScript checks that every property and method the interface requires is actually present with a compatible type. Unlike extends, implements does not provide any inherited implementation; it is purely a compile-time contract check.