Two Decorators, One Keyword, Zero Compatibility
A team wanted to write a standard decorator for a new logging library and switched off experimentalDecorators across the repo. Their NestJS service started with undefined dependencies in every controller, because Nest relies on the metadata that only the legacy decorators emit.
TypeScript has two decorator features that share one syntax: the legacy experimental decorators that frameworks such as NestJS and Angular are built on, and the standard TC39 decorators supported since TypeScript 5.0. Below is how each works, field, accessor and class decorators under the new proposal, where the metadata went, and how to decide which to use.
- You've seen
Reflect.getMetadata('design:paramtypes', ...)returnundefinedand had no idea why - NestJS or TypeORM examples use decorators that look nothing like the ones in the TypeScript 5 release notes
- You tried turning off
experimentalDecoratorsin an existing app and half the codebase stopped compiling - You're not sure whether
emitDecoratorMetadatais doing anything in your current build
Neither proposal is going away soon — legacy decorators still power most dependency-injection frameworks in production. Knowing which one you're looking at, and why they can't be mixed, saves a specific kind of confusing afternoon.

