TypeScript Decorators: Migrating from Legacy to TC39 Standard
TC39 standard decorators break compatibility with experimentalDecorators: parameter decorators are gone and metadata handling changed. A code-driven migration guide for production teams.
Starting with TypeScript 5.0, standard TC39 decorators ship by default, but moving off legacy experimentalDecorators is far from a simple flag flip. The two systems use fundamentally different signatures: legacy decorators received different arguments depending on target (constructors, descriptors, indices), while standard decorators always take a decorated value plus a context object. Instead of mutating prototypes directly, class decorators must now return a replacement constructor or rely on context.addInitializer for side effects.
One of the biggest breaking changes is metadata handling. The reflect-metadata-based global metadata store is replaced by context.metadata, an object scoped to each decoration context rather than shared globally. This eliminates a 20-30KB polyfill dependency and prevents cross-class metadata pollution, but it also means any code relying on Reflect.getMetadata calls needs rewriting. Parameter decorators are gone entirely from the TC39 spec, forcing dependency-injection and validation patterns to move metadata collection to the method or constructor level.
For production teams, the pragmatic path is incremental: migrate decorators when touching new features rather than rewriting stable code outright. Conditional exports and type-only imports let legacy and standard decorators coexist in the same codebase, enabling the compiler flag to be adopted gradually across releases. This staged approach helps engineering teams avoid the migration debt that builds up the longer experimentalDecorators stays in production.