Quick Overview
A decorator is a function that receives the thing it decorates and returns a replacement, so it wraps behaviour rather than editing it. TypeScript 5.0 switched to the Stage 3 standard, and the signatures changed.
A Decorator is a special syntax (@decoratorName) that allows you to attach reusable aspect-oriented behavior (logging, validation, auto-binding) to classes, methods, fields, and accessors.
TypeScript 5.0 introduced support for the official Stage 3 ECMAScript Decorator standard without needing legacy experimentalDecorators flags!
A method decorator receives the original target function and a ClassMethodDecoratorContext object:
// Method Logger Decorator
function loggedMethod<This, Args extends any[], Return>(
target: (this: This, ...args: Args) => Return,
context: ClassMethodDecoratorContext<This, (this: This, ...args: Args) => Return>
) {
const methodName = String(context.name);
return function (this: This, ...args: Args): Return {
console.log(`[LOG]: Entering method '${methodName}'...`);
const result = target.call(this, ...args);
console.log(`[LOG]: Exiting method '${methodName}'.`);
return result;
};
}
class UserService {
@loggedMethod
public deleteUser(id: string) {
console.log("Deleting user:", id);
}
}
const service = new UserService();
service.deleteUser("usr_42");
// Output:
// [LOG]: Entering method 'deleteUser'...
// Deleting user: usr_42
// [LOG]: Exiting method 'deleteUser'.
experimentalDecorators: true. Avoid mixing legacy experimental decorator syntax with modern standard decorators!Use decorators for clean aspect logging and ORM entity mapping. Next, let's finish our 30-lesson track with Project References and Monorepos!
TypeScript erases entirely at build time, so a `string` annotation produces no runtime check whatsoever. A value arriving from an API is whatever the server actually sent, regardless of what the annotation claims.
`let x = "GET"` infers `string` because the binding can change; `const x = "GET"` infers the literal `"GET"`. That widening rule is why object properties need `as const` to stay narrow.
`string[]` is any number of strings; `[string, number]` is exactly two, in that order. `readonly` removes the mutating methods at compile time, so `push` becomes a type error rather than a runtime surprise.